<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 4.2.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css">
  <link rel="stylesheet" href="//cdn.jsdelivr.net/gh/fancyapps/fancybox@3/dist/jquery.fancybox.min.css">
  <link rel="stylesheet" href="/lib/pace/pace-theme-minimal.min.css">
  <script src="/lib/pace/pace.min.js"></script>

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"lanqilu.github.io","root":"/","scheme":"Gemini","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":true},"copycode":{"enable":true,"show_result":true,"style":null},"back2top":{"enable":true,"sidebar":true,"scrollpercent":true},"bookmark":{"enable":false,"color":"#395ca3","save":"auto"},"fancybox":true,"mediumzoom":false,"lazyload":false,"pangu":true,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="参考资料：《Java核心技术 卷Ⅰ》（原书第11版）第3章">
<meta property="og:type" content="article">
<meta property="og:title" content="Java的基本程序设计">
<meta property="og:url" content="https://lanqilu.github.io/2019/11/29/Java/Java-03-%E5%9F%BA%E6%9C%AC%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/index.html">
<meta property="og:site_name" content="Halo">
<meta property="og:description" content="参考资料：《Java核心技术 卷Ⅰ》（原书第11版）第3章">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2019-11-29T15:10:02.000Z">
<meta property="article:modified_time" content="2020-09-22T07:54:53.619Z">
<meta property="article:author" content="Lanqilu">
<meta property="article:tag" content="Java">
<meta name="twitter:card" content="summary">

<link rel="canonical" href="https://lanqilu.github.io/2019/11/29/Java/Java-03-%E5%9F%BA%E6%9C%AC%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>Java的基本程序设计 | Halo</title>
  
    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-161500949-1"></script>
    <script data-pjax>
      if (CONFIG.hostname === location.hostname) {
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());
        gtag('config', 'UA-161500949-1');
      }
    </script>


  <script data-pjax>
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?256151d1651e9d73ec980b2fc69de8f6";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
  </script>




  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">Halo</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-fw fa-home"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-fw fa-tags"></i>标签<span class="badge">39</span></a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-fw fa-th"></i>分类<span class="badge">18</span></a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-fw fa-archive"></i>归档<span class="badge">85</span></a>

  </li>
        <li class="menu-item menu-item-python">

    <a href="/categories/Python/" rel="section"><i class="fa fa-fw fa-code"></i>Python</a>

  </li>
        <li class="menu-item menu-item-java">

    <a href="/categories/Java/" rel="section"><i class="fa fa-fw fa-code"></i>Java</a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result">
  <div id="no-result">
    <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
  </div>
</div>

    </div>
  </div>

</div>
    </header>

    
  <div class="reading-progress-bar"></div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://lanqilu.github.io/2019/11/29/Java/Java-03-%E5%9F%BA%E6%9C%AC%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="http://img.whl123456.top/image/avatar.jpg">
      <meta itemprop="name" content="Lanqilu">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Halo">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          Java的基本程序设计
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2019-11-29 23:10:02" itemprop="dateCreated datePublished" datetime="2019-11-29T23:10:02+08:00">2019-11-29</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2020-09-22 15:54:53" itemprop="dateModified" datetime="2020-09-22T15:54:53+08:00">2020-09-22</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Java/" itemprop="url" rel="index"><span itemprop="name">Java</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <div class="note info no-icon">
            <p>参考资料：</p><ul><li>《Java核心技术 卷Ⅰ》（原书第11版）第3章</li></ul>
          </div>

<a id="more"></a>

<hr>
<h2 id="一个简单的Java程序"><a href="#一个简单的Java程序" class="headerlink" title="一个简单的Java程序"></a>一个简单的Java程序</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FirstSample</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"We will not use 'Hello, World!'"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="Java程序概览"><a href="#Java程序概览" class="headerlink" title="Java程序概览"></a>Java程序概览</h3><p>在详细介绍 Java 句法之前，我们先花点儿时间概述 Java 程序。Java 程序由一个或多个Java 源码文件（或叫编译单元）组成。</p>
<p><strong>包声明和导入语句</strong>：每个编译单元都以可选的 package 声明开始，后面跟着零个或多个 import 声明。这些声明指定一个命名空间，编译单元中定义的名称都在这个命名空间里，而且还指定了编译单元从哪些命名空间中导入名称。</p>
<p><strong>类定义</strong>：在可选的 package 和 import 声明之后，是零个或多个引用类型定义。这些往往都是 class 或 interface 定义。</p>
<p><strong>包含实际代码的方法</strong>：在引用类型的定义体中有一些成员，例如字段、方法和构造方法。其中，方法是最重要的成员类型。方法是一段由语句组成的 Java 代码。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Hello</span> </span>&#123;</span><br><span class="line">    <span class="comment">// Java程序的入口方法，程序将从这里开始执行</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>&#123;</span><br><span class="line">        <span class="comment">// 向控制台打印一条语句，Java程序严格区分大小写</span></span><br><span class="line">        System.out.println(<span class="string">"Hello Word!"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>所有的程序都必须放到类的定义里</p>
<p>如果某个类能被解释器直接解释执行，则这个类里必须包含<code>main</code>方法，而且<code>main</code>方法必须使用<code>pubilc static void</code>来修饰，且<code>main</code>方法的形必须是字符串数组类型(<code>String[] args</code>是字符串数组的形式)</p>
<h3 id="基本规则与命名规范"><a href="#基本规则与命名规范" class="headerlink" title="基本规则与命名规范"></a>基本规则与命名规范</h3><p>编写 Java 程序时，应注意以下几点：</p>
<ul>
<li><p><strong>大小写敏感</strong>：Java 是大小写敏感的，这就意味着标识符 Hello 与 hello 是不同的。</p>
</li>
<li><p>Java 会忽略空格、制表符、换行符和其他空白，除非这些符号出现在引号或字符串字面量中。为了易读，程序员一般会使用空白格式化和缩进代码。</p>
</li>
<li><p><strong>类名、接口名</strong>：对于所有的类来说，类名的首字母应该大写。多单词组成时，所有单词的首字母大写：XxxYyyZzz。</p>
</li>
<li><p><strong>变量名、方法名</strong>：所有的方法名都应该以小写字母开头。多单词组成时，第一个单词首字母小写，第二个单词开始每个单词首字母大写：xxxYyyZzz 。</p>
</li>
<li><p><strong>源文件名</strong>：如果源代码定义了一个<code>public</code>类，则该源文件的主文件名必须与该<code>public</code>类名相同，文件名的后缀为 <strong>.java</strong>。（如果文件名和类名不相同则会导致编译错误）。</p>
<blockquote>
<p>由于源文件文件名必须与<code>puclic</code>类名相同，因此一个Java源文件只能定义一个<code>public</code>类</p>
</blockquote>
</li>
<li><p><strong>主方法入口</strong>：所有的 Java 程序由 <code>public static void main(String []args)</code>方法开始执行。</p>
</li>
<li><p><strong>包名</strong>：多单词组成时所有字母都小写：xxxyyyzzz</p>
</li>
<li><p>常量名：所有字母都大写。多单词时每个单词用下划线连接：XXX_YYY_ZZZ</p>
</li>
</ul>
<h2 id="注释"><a href="#注释" class="headerlink" title="注释"></a>注释</h2><p>注释是使用自然语言编写的文本，供某一程序的人类读者阅读。Java 编译器会忽略注释。Java 支持三种注释。</p>
<p>第一种是单行注释，以 <code>//</code> 字符开始，直到行尾结束。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 这是注释...</span></span><br></pre></td></tr></table></figure>

<p>第二种是多行注释，以 <code>/*</code> 字符开始，不管有多少行，直到 <code>*/</code> 字符结束，一般用于多行注释。这种注释不能嵌套，即 <code>/* */</code> 中不能再有 <code>/* */</code>。编写多行注释时，程序员经常使用额外的 <code>*</code> 字符，突出注释的内容。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> * 这是注释</span></span><br><span class="line"><span class="comment"> * blablabla...</span></span><br><span class="line"><span class="comment"> * 这也是注释</span></span><br><span class="line"><span class="comment"> */</span></span><br></pre></td></tr></table></figure>

<p>第三种注释是第二种的一个特例。如果注释以 <code>/**</code> 开头，会被当成特殊的文档注释。和普通的多行注释一样，文档注释也以 <code>*/</code> 结尾，而且不能嵌套。如果你编写了一个 Java 类，希望让其他程序员使用，可以直接在源码中嵌入关于这个类和其中每个方法的文档。名为javadoc 的程序会提取这些文档，经过处理后生成这个类的在线文档。文档注释中可以包含 HTML 标签和javadoc 能理解的其他句法。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 可以用来自动创建文档的注释</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@auther</span> lanqilu</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Hello</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"Hello, world!"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这种特殊的多行注释需要写在类和方法的定义处，可以用于自动创建文档。</p>
<p>类文档标记</p>
<ul>
<li><code>@version 版本信息</code></li>
<li><code>@author 作者信息</code></li>
</ul>
<p>方法文档标记</p>
<ul>
<li><code>@param 参数名 说明</code></li>
<li><code>@return 说明</code></li>
<li><code>@exception 完整类名 说明</code></li>
<li><code>@deprecated</code></li>
</ul>
<p>Java程序对格式没有明确的要求，多几个空格或者回车不影响程序的正确性，但是我们要养成良好的编程习惯，注意遵守Java社区约定的编码格式。</p>
<h2 id="词法结构"><a href="#词法结构" class="headerlink" title="词法结构"></a>词法结构</h2><h3 id="保留字"><a href="#保留字" class="headerlink" title="保留字"></a>保留字</h3><table>
<thead>
<tr>
<th><code>abstract</code></th>
<th><strong><code>const</code></strong></th>
<th><strong><code>final</code></strong></th>
<th><strong><code>int</code></strong></th>
<th><strong><code>public</code></strong></th>
<th><strong><code>throw</code></strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong><code>asser</code></strong></td>
<td><strong><code>continue</code></strong></td>
<td><strong><code>finally</code></strong></td>
<td><strong><code>interface</code></strong></td>
<td><strong><code>return</code></strong></td>
<td><strong><code>throws</code></strong></td>
</tr>
<tr>
<td><strong><code>boolean</code></strong></td>
<td><strong><code>default</code></strong></td>
<td><strong><code>float</code></strong></td>
<td><strong><code>long</code></strong></td>
<td><strong><code>short</code></strong></td>
<td><strong><code>transient</code></strong></td>
</tr>
<tr>
<td><strong><code>break</code></strong></td>
<td><strong><code>do</code></strong></td>
<td><strong><code>for</code></strong></td>
<td><strong><code>native</code></strong></td>
<td><strong><code>static</code></strong></td>
<td><strong><code>true</code></strong></td>
</tr>
<tr>
<td><strong><code>byte</code></strong></td>
<td><strong><code>double</code></strong></td>
<td><strong><code>goto</code></strong></td>
<td><strong><code>new</code></strong></td>
<td><strong><code>strictfp</code></strong></td>
<td><strong><code>try</code></strong></td>
</tr>
<tr>
<td><strong><code>case</code></strong></td>
<td><strong><code>else</code></strong></td>
<td><strong><code>if</code></strong></td>
<td><strong><code>null</code></strong></td>
<td><strong><code>super</code></strong></td>
<td><strong><code>void</code></strong></td>
</tr>
<tr>
<td><strong><code>catch</code></strong></td>
<td><strong><code>enum</code></strong></td>
<td><strong><code>implements</code></strong></td>
<td><strong><code>package</code></strong></td>
<td><strong><code>switch</code></strong></td>
<td><strong><code>volatile</code></strong></td>
</tr>
<tr>
<td><strong><code>char</code></strong></td>
<td><strong><code>extends</code></strong></td>
<td><strong><code>import</code></strong></td>
<td><strong><code>private</code></strong></td>
<td><strong><code>synchronized</code></strong></td>
<td><strong><code>while</code></strong></td>
</tr>
<tr>
<td><strong><code>class</code></strong></td>
<td><strong><code>false</code></strong></td>
<td><strong><code>instanceof</code></strong></td>
<td><strong><code>protected</code></strong></td>
<td><strong><code>this</code></strong></td>
<td></td>
</tr>
</tbody></table>
<blockquote>
<p>注意：</p>
<p>虽然 Java 语言不使用 <code>const</code> 和 <code>goto</code>，但它们也是保留字；</p>
<p><code>interface</code> 还有另外一种形式——<code>@interface</code>，用来定义注解类型。</p>
<p>有些保留字（尤其是 <code>final</code> 和 <code>default</code>）根据不同的上下文有不同的意义。</p>
</blockquote>
<h3 id="标识符"><a href="#标识符" class="headerlink" title="标识符"></a>标识符</h3><p>Java 所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符。</p>
<p>关于 Java 标识符，有以下几点需要注意：</p>
<ul>
<li>所有的标识符都应该以字母（A-Z 或者 a-z）,美元符（$）、或者下划线（_）开始</li>
<li>数字不可以开头</li>
<li>首字符之后可以是字母（A-Z 或者 a-z）,美元符（$）、下划线（_）或数字的任何字符组合</li>
<li>关键字、保留字不能用作标识符</li>
<li>标识符是大小写敏感的，不能包含空格</li>
<li>合法标识符举例：age、$salary、_value、__1_value</li>
<li>非法标识符举例：123abc、-salary</li>
</ul>
<blockquote>
<p>货币符号主要用在自动生成的源码中，例如 javac 生成的代码。不在标识符中使用货币符号，可以避免自己的标识符和自动生成的标识符冲突。</p>
</blockquote>
<h3 id="字面量"><a href="#字面量" class="headerlink" title="字面量"></a>字面量</h3><p>字面量是直接出现在源码中的值，包括整数、浮点数、单引号中的单个字符、双引号中的字符串，以及保留字 true、false 和 null。</p>
<h3 id="类"><a href="#类" class="headerlink" title="类"></a>类</h3><p>因为Java是面向对象的语言，一个程序的基本单位就是<code>class</code>，<code>class</code>是关键字，这里定义的<code>class</code>名字就是<code>Hello</code>：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Hello</span> </span>&#123; <span class="comment">// 类名是Hello</span></span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125; <span class="comment">// class定义结束</span></span><br></pre></td></tr></table></figure>

<p>类名要求：</p>
<ul>
<li>类名必须以英文字母开头，后接字母，数字和下划线的组合</li>
<li>习惯以大写字母开头</li>
</ul>
<h3 id="方法"><a href="#方法" class="headerlink" title="方法"></a>方法</h3><p>注意到<code>public</code>是访问修饰符，表示该<code>class</code>是公开的。不写<code>public</code>，也能正确编译，但是这个类将无法从命令行执行。在<code>class</code>内部，可以定义若干方法（method）：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Hello</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123; <span class="comment">// 方法名是main</span></span><br><span class="line">        <span class="comment">// 方法代码...</span></span><br><span class="line">    &#125; <span class="comment">// 方法定义结束</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>方法定义了一组执行语句，方法内部的代码将会被依次顺序执行。这里的方法名是<code>main</code>，返回值是<code>void</code>，表示没有任何返回值。</p>
<p>我们注意到<code>public</code>除了可以修饰<code>class</code>外，也可以修饰方法。而关键字<code>static</code>是另一个修饰符，它表示静态方法，后面我们会讲解方法的类型，目前，我们只需要知道，Java入口程序规定的方法必须是静态方法，方法名必须为<code>main</code>，括号内的参数必须是<code>String</code>数组。</p>
<p>方法名也有命名规则，命名和<code>class</code>一样，但是首字母小写。</p>
<p>在方法内部，语句才是真正的执行代码。Java的每一行语句必须以<strong>分号结束</strong>：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Hello</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"Hello, world!"</span>); <span class="comment">// 语句</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h3 id="变量"><a href="#变量" class="headerlink" title="变量"></a>变量</h3><p> 在Java中，变量<strong>必须先定义后使用</strong>，在定义变量的时候，可以给它一个初始值。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> x = <span class="number">100</span>; <span class="comment">// 定义int类型变量x，并赋予初始值100</span></span><br><span class="line">        System.out.println(x); <span class="comment">// 打印该变量的值</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p> 变量的一个重要特点是可以重新赋值， 还可以赋值给其他变量</p>
<p><strong>变量命名</strong></p>
<ul>
<li><p>名字必须以字母或下划线(<code>_</code>)开头</p>
</li>
<li><p>名字中所有其他字符必须是字母、数字和下划线。名字中不能出现空格或其他特殊字符。</p>
</li>
<li><p>名字不能是任何保留词</p>
</li>
</ul>
<h2 id="数据类型"><a href="#数据类型" class="headerlink" title="数据类型"></a>数据类型</h2><p>Java是一种强类型语言。这就意味着必须为每一个变量声明一种类型。</p>
<p>基本数据类型是CPU可以直接进行运算的类型。Java 支持八种基本数据类型，包括一种布尔类型、一种字符类型、四种整数类型和两种浮点数类型：</p>
<ul>
<li>整数类型：byte，short，int，long</li>
<li>浮点数类型：float，double</li>
<li>字符类型：char</li>
<li>布尔类型：boolean</li>
</ul>
<p>除了基本数据类型之外，Java 还支持称为引用类型的非基本数据类型：</p>
<ul>
<li>类（class）</li>
<li>接口（interface）</li>
<li>数组（array）</li>
</ul>
<blockquote>
<p>Java有一个能够表示任意精度的算术包，通常称为“大数”（big number）。虽然称为大数但它并不是一种基本Java类型，而是一个Java对象。</p>
</blockquote>
<h3 id="基本数据类型"><a href="#基本数据类型" class="headerlink" title="基本数据类型"></a>基本数据类型</h3><p>Java语言提供了八种基本类型。六种数字类型（四个整数型，两个浮点型），一种字符类型，还有一种布尔型。</p>
<p><strong>byte：</strong></p>
<ul>
<li>byte 数据类型是8位、有符号的，以二进制补码表示的整数；</li>
<li>最小值是 <strong>-128（-2<sup>7</sup>）</strong>；</li>
<li>最大值是 <strong>127（2<sup>7</sup> -1）</strong>；</li>
<li>默认值是 <strong>0</strong>；</li>
<li>byte 类型用在大型数组中节约空间，主要代替整数，因为 byte 变量占用的空间只有 int 类型的四分之一；</li>
<li>例子：<code>byte a = 100;</code>，<code>byte b = -50;</code>。</li>
</ul>
<p><strong>short：</strong></p>
<ul>
<li>short 数据类型是 16 位、有符号的以二进制补码表示的整数</li>
<li>最小值是 <strong>-32768（-2<sup>15</sup>）</strong>；</li>
<li>最大值是 <strong>32767（2<sup>15</sup> - 1）</strong>；</li>
<li>Short 数据类型也可以像 byte 那样节省空间。一个short变量是int型变量所占空间的二分之一；</li>
<li>默认值是 <strong>0</strong>；</li>
<li>例子：<code>short s = 1000;</code>，<code>short r = -20000;</code>。</li>
</ul>
<p><strong>int：</strong></p>
<ul>
<li>int 数据类型是32位、有符号的以二进制补码表示的整数；</li>
<li>最小值是 <strong>-2,147,483,648（-2<sup>31</sup>）</strong>；</li>
<li>最大值是 <strong>2,147,483,647（2<sup>31</sup> - 1）</strong>；</li>
<li>一般地整型变量默认为 int 类型；</li>
<li>默认值是 <strong>0</strong> ；</li>
<li>例子：<code>int a = 100000;</code>， <code>int b = -200000;</code>。</li>
</ul>
<p><strong>long：</strong></p>
<ul>
<li>long 数据类型是 64 位、有符号的以二进制补码表示的整数；</li>
<li>最小值是 <strong>-9,223,372,036,854,775,808（-2<sup>63</sup>）</strong>；</li>
<li>最大值是 <strong>9,223,372,036,854,775,807（2<sup>63</sup> -1）</strong>；</li>
<li>这种类型主要使用在需要比较大整数的系统上；</li>
<li>默认值是 <strong>0L</strong>；</li>
<li>例子： <code>long a = 100000L;</code>，<code>long b = -200000L;</code>。<br>“L”理论上不分大小写，但是若写成”l”容易与数字”1”混淆，不容易分辩。所以最好大写。</li>
</ul>
<p><strong>float：</strong></p>
<ul>
<li>float 数据类型是单精度、32位、符合IEEE 754标准的浮点数；</li>
<li>float 在储存大型浮点数组的时候可节省内存空间；</li>
<li>默认值是 <strong>0.0f</strong>；</li>
<li>浮点数不能用来表示精确的值，如货币；</li>
<li>例子：<code>float f = 234.5f;</code></li>
</ul>
<p><strong>double：</strong></p>
<ul>
<li>double 数据类型是双精度、64 位、符合IEEE 754标准的浮点数；</li>
<li>浮点数的默认类型为double类型；</li>
<li>double类型同样不能表示精确的值，如货币；</li>
<li>默认值是 <strong>0.0d</strong>；</li>
<li>例子：<code>double d = 123.4;</code></li>
</ul>
<p><strong>boolean：</strong></p>
<ul>
<li>boolean数据类型表示一位的信息；</li>
<li>只有两个取值：true 和 false；</li>
<li>这种类型只作为一种标志来记录 true/false 情况；</li>
<li>默认值是 <strong>false</strong>；</li>
<li>例子：<code>boolean one = true;</code></li>
</ul>
<p><strong>char：</strong></p>
<ul>
<li>char类型是一个<strong>单一</strong>的 16 位 Unicode 字符和转义字符</li>
<li>最小值是 <strong>\u0000</strong>（即为0）；</li>
<li>最大值是 <strong>\uffff</strong>（即为65,535）；</li>
<li>char 数据类型可以储存任何字符；</li>
<li>例子：<code>char letter = &#39;A&#39;;  //使用单引号</code></li>
</ul>
<h3 id="整数类型"><a href="#整数类型" class="headerlink" title="整数类型"></a>整数类型</h3><p>整型用于表示没有小数部分的数值，允许是负数。</p>
<p>Java 中的整数类型有 byte、short、int 和 long 四种。这四种类型之间唯一的区别是位数，即能表示的数字范围有所不同。对于整型类型，Java只定义了带符号的整型，因此，最高位的bit表示符号位（0表示正数，1表示负数）。各种整型能表示的最大范围如下：</p>
<table>
<thead>
<tr>
<th>类型</th>
<th>存储要求</th>
<th>取值范围</th>
</tr>
</thead>
<tbody><tr>
<td>int</td>
<td>4字节</td>
<td>-2147483648 ~ 2147483647（超过20亿）</td>
</tr>
<tr>
<td>short</td>
<td>2字节</td>
<td>-32768 ~ 32767</td>
</tr>
<tr>
<td>long</td>
<td>8字节</td>
<td>-9223372036854775808 ~ 9223372036854775807</td>
</tr>
<tr>
<td>byte</td>
<td>1字节</td>
<td>-128 ~ 127</td>
</tr>
</tbody></table>
<blockquote>
<p>在Java中，整型的范围与运行Java代码的机器无关。这就解决了软件从一个平台移植到另一平台，或者在同一平台中的不同操作系统之间进行移植给程序员带来的诸多问题。与此相反，C和C++程序会针对不同的处理器选择最为高效的整型。</p>
</blockquote>
<ul>
<li>长整型数值有一个后缀L或l（如4000000000L）</li>
<li>十六进制数值有一个前缀0x或0X（如0xCAFE）</li>
<li>八进制有一个前缀0，例如，010对应十进制中的8。很显然，八进制表示法比较容易混淆</li>
<li>从Java7开始，加上前缀0b或0B就可以写二进制数。例如，0b1001</li>
<li>同样从Java7开始，还可以为数字字面量加下划线，如1_000_000。这些下划线只是为了让人更易读。Java编译器会去除这些下划线。</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> i = <span class="number">2147483647</span>;</span><br><span class="line">        <span class="keyword">int</span> i2 = -<span class="number">2147483648</span>;</span><br><span class="line">        <span class="keyword">int</span> i3 = <span class="number">2_000_000_000</span>; 	<span class="comment">// 加下划线更容易识别</span></span><br><span class="line">		<span class="keyword">int</span> i4 = <span class="number">0377</span>;           	<span class="comment">// 使用八进制表示的十进制数255</span></span><br><span class="line">        <span class="keyword">int</span> i4 = <span class="number">0xff0000</span>; 			<span class="comment">// 十六进制表示的16711680</span></span><br><span class="line">        <span class="keyword">int</span> i5 = <span class="number">0b1000000000</span>; 		<span class="comment">// 二进制表示的512</span></span><br><span class="line">        <span class="keyword">long</span> l = <span class="number">9000000000000000000L</span>; <span class="comment">// long型的结尾需要加L</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在 Java 中，如果整数运算超出了指定整数类型的范围，不会上溢或下溢，而是直接回绕。如果发生了这种情况，Java 编译器和解释器都不会发出任何形式的警告。进行整数运算时，必须确保使用的类型取值范围能满足计算需要。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">byte</span> b1 = <span class="number">127</span>, b2 = <span class="number">1</span>;       <span class="comment">// byte类型的最大值是127 </span></span><br><span class="line"><span class="keyword">byte</span> sum = (<span class="keyword">byte</span>)(b1 + b2);  <span class="comment">// 加法运算的结果直接回绕到-128，即byte类型的最小值</span></span><br></pre></td></tr></table></figure>

<p>每一种整数类型都有对应的包装类：<code>Byte</code>、<code>Short</code>、<code>Integer</code> 和 <code>Long</code>。这些类都定义了 <code>MIN_VALUE</code> 和 <code>MAX_VALUE</code> 常量，表示相应的取值范围。而且还定义了一些有用的静态方法，例如<code>Byte.parseByte()</code> 和 <code>Integer.parseInt()</code>，作用是把字符串转换成整数。</p>
<h3 id="浮点数类型"><a href="#浮点数类型" class="headerlink" title="浮点数类型"></a>浮点数类型</h3><p>浮点类型用于表示有小数部分的数值</p>
<p>浮点类型的数就是小数，因为小数用科学计数法表示的时候，小数点是可以“浮动”的，如1234.5可以表示成12.345x10<sup>2</sup>，也可以表示成1.2345x10<sup>3</sup>，所以称为浮点数。</p>
<p><code>float</code> 类型是 32 位单精度浮点数，<code>double</code> 是 64 位双精度浮点数。</p>
<p>对于<code>float</code>类型，需要加上<code>f</code>或<code>F</code>后缀。没有后缀<code>f</code>或<code>F</code>的浮点数值总是默认为<code>double</code>类型。</p>
<p>下面是定义浮点数的例子：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">float</span> f1 = <span class="number">3.14f</span>;</span><br><span class="line"><span class="keyword">float</span> f2 = <span class="number">3.14e38f</span>; <span class="comment">// 科学计数法表示的3.14x10^38</span></span><br><span class="line"><span class="keyword">double</span> d = <span class="number">1.79e308</span>;</span><br><span class="line"><span class="keyword">double</span> d2 = -<span class="number">1.79e308</span>;</span><br><span class="line"><span class="keyword">double</span> d3 = <span class="number">4.9e-324</span>; <span class="comment">// 科学计数法表示的4.9x10^-324</span></span><br></pre></td></tr></table></figure>

<p>浮点数可表示的范围非常大，<code>float</code>类型可最大表示3.4x10<sup>38</sup>，而<code>double</code>类型可最大表示1.79x10<sup>308</sup>。</p>
<p>除了表示普通的数字之外，<code>float</code> 和 <code>double</code> 类型还能表示四个特殊的值：</p>
<ul>
<li>正无穷大：如果浮点数运算的结果超出了 <code>float</code> 或 <code>double</code> 能表示的范围上限，得到的是正无穷大。</li>
<li>负无穷大：如果浮点数的运算结果超出了 <code>float</code> 或 <code>double</code> 能表示的范围下限，得到的是负无穷大。</li>
<li>零：Java 的浮点类型区分正零和负零，具体是哪个值取决于从哪个方向出现的下溢。在实际使用中，正零和负零的表现基本一样。</li>
<li>NaN：是“Not-a-Number”的简称，表示“不是数字”。如果浮点数运算不合法，例如 0.0/0.0，得到的就是 NaN。</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">double</span> inf = <span class="number">1.0</span>/<span class="number">0.0</span>;          <span class="comment">// 无穷大 </span></span><br><span class="line"><span class="keyword">double</span> neginf = -<span class="number">1.0</span>/<span class="number">0.0</span>;      <span class="comment">// 负无穷大</span></span><br><span class="line"><span class="keyword">double</span> negzero = -<span class="number">1.0</span>/inf;     <span class="comment">// 负零 </span></span><br><span class="line"><span class="keyword">double</span> NaN = <span class="number">0.0</span>/<span class="number">0.0</span>;          <span class="comment">// NaN</span></span><br></pre></td></tr></table></figure>

<p>Java 浮点数类型能处理到无穷大的上溢以及到零的下溢，因此浮点数运算从不抛出异常，就算执行非法运算也没事，例如零除以零，或计算负数的平方根。</p>
<p>float 和 double 基本类型都有对应的类，分别为 Float 和 Double。这两个类都定义了一些有用的常量：<code>MIN_VALUE</code>、<code>MAX_VALUE</code>、<code>NEGATIVE_INFINITY</code>、<code>POSITIVE_INFINITY</code> 和 <code>NaN</code>。</p>
<p>无穷大浮点数的表现和设想的一样，例如，无穷大之间的加减运算得到的还是无穷大。</p>
<p>负零的表现几乎和正零一样，而且事实上，相等运算符 == 会告诉你，负零和正零是相等的。区分负零、正零和普通的零有一种方法——把它作为被除数：1.0/0.0 得到的是正无穷大，但是 1.0 除以负零得到的是负无穷大。</p>
<p>因为 NaN 不是数字，所以 == 运算符会告诉我们它不等于任何其他数字，甚至包括它自己。若想检查某个 float 或double 值是否为 NaN，必须使用 <code>Float.isNaN()</code> 或 <code>Double.isNaN()</code> 方法。</p>
<blockquote>
<p>浮点数值<strong>不适用</strong>无法接受舍入误差的金融计算。因是浮点数值采用二级制系统表示，而在二进制系统中无法精确地表示分数1/10。这就好像十进制无法精确地表示分数1/3一样。如果在数值计算中不允许有任何舍入误差，就应该使用<code>BigDecimal</code>类</p>
</blockquote>
<h3 id="布尔类型"><a href="#布尔类型" class="headerlink" title="布尔类型"></a>布尔类型</h3><p>布尔类型<code>boolean</code>只有<code>true</code>和<code>false</code>两个值，布尔类型总是关系运算的计算结果：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">boolean</span> b1 = <span class="keyword">true</span>;</span><br><span class="line"><span class="keyword">boolean</span> b2 = <span class="keyword">false</span>;</span><br><span class="line"><span class="keyword">boolean</span> isGreater = <span class="number">5</span> &gt; <span class="number">3</span>; <span class="comment">// 计算结果为true</span></span><br><span class="line"><span class="keyword">int</span> age = <span class="number">12</span>;</span><br><span class="line"><span class="keyword">boolean</span> isAdult = age &gt;= <span class="number">18</span>; <span class="comment">// 计算结果为false</span></span><br></pre></td></tr></table></figure>

<p>Java语言对布尔类型的存储并没有做规定，因为理论上存储布尔类型只需要1 bit，但是通常JVM内部会把<code>boolean</code>表示为4字节整数。</p>
<blockquote>
<p>布尔类型既不是整数类型也不是对象类型，而且不能使用不兼容的值代替布尔类型（如不能使用1或0代表true和false）。</p>
</blockquote>
<h3 id="字符类型"><a href="#字符类型" class="headerlink" title="字符类型"></a>字符类型</h3><p>字符类型<code>char</code>表示单个字符。</p>
<blockquote>
<p>如今有些Unicode字符可以用一个<code>char</code>值描述，另外一些Unicode字符则需要两个<code>char</code>值。</p>
</blockquote>
<p>Java的<code>char</code>类型除了可表示标准的ASCII外，还可以表示一个Unicode字符和转义字符（如<code>‘\n’</code>表示换行符），如果想在 Java 程序中使用字符字面量，只需把字符放在单引号中即可</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">char</span> a = <span class="string">'A'</span>;</span><br><span class="line">        <span class="keyword">char</span> zh = <span class="string">'中'</span>;</span><br><span class="line">        System.out.println(a);</span><br><span class="line">        System.out.println(zh);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>注意<code>char</code>类型使用<strong>单引号</strong><code>&#39;</code>，且仅有一个字符，要和双引号<code>&quot;</code>的字符串类型区分开。</p>
</blockquote>
<p>字符可以转换成整数类型，也可以从整数类型转换而来。字符类型对应的是 16 位整数类型。字符类型与 byte、short、int 和 long 不同，没有符号。Character 类定义了一些有用的静态方法（static method），用于处理字符，例如 <code>isDigit()</code>、<code>isJavaLetter()</code>、<code>isLowerCase()</code> 和 <code>toUpperCase()</code>。</p>
<h3 id="基本类型之间的转换"><a href="#基本类型之间的转换" class="headerlink" title="基本类型之间的转换"></a>基本类型之间的转换</h3><p><strong>整型、实型（常量）、字符型数据可以混合运算。运算中，不同类型的数据先转化为同一类型，然后进行运算。</strong></p>
<p>转换从低级到高级。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">byte ────▶short</span><br><span class="line">               │</span><br><span class="line">               ▼</span><br><span class="line">char ────▶  int ────▶ long ────▶ float ────▶ double</span><br></pre></td></tr></table></figure>

<p>数据类型转换必须满足如下规则：</p>
<ul>
<li>不能对boolean类型进行类型转换。</li>
<li>不能把对象类型转换成不相关类的对象。</li>
<li>在把容量大的类型转换为容量小的类型时必须使用强制类型转换。</li>
<li>转换过程中可能导致溢出或损失精度。</li>
<li>浮点数到整数的转换是通过舍弃小数得到，而不是四舍五入。</li>
</ul>
<h3 id="数据类型其他有关情况"><a href="#数据类型其他有关情况" class="headerlink" title="数据类型其他有关情况"></a>数据类型其他有关情况</h3><h4 id="常量"><a href="#常量" class="headerlink" title="常量"></a>常量</h4><p>定义变量的时候，如果加上<code>final</code>修饰符，这个变量就变成了常量：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">final</span> <span class="keyword">double</span> PI = <span class="number">3.14</span>; <span class="comment">// PI是一个常量</span></span><br><span class="line"><span class="keyword">double</span> r = <span class="number">5.0</span>;</span><br><span class="line"><span class="keyword">double</span> area = PI * r * r;</span><br><span class="line">PI = <span class="number">300</span>; <span class="comment">// compile error!</span></span><br></pre></td></tr></table></figure>

<p>常量在定义时进行<strong>初始化后就不可再次赋值</strong>，再次赋值会导致编译错误。</p>
<p>常量的作用是用有意义的变量名来避免魔术数字（Magic number），例如，不要在代码中到处写<code>3.14</code>，而是定义一个常量。如果将来需要提高计算精度，我们只需要在常量的定义处修改，例如，改成<code>3.1416</code>，而不必在所有地方替换<code>3.14</code>。</p>
<p>根据习惯，<strong>常量名通常全部大写</strong>。</p>
<h4 id="var关键字"><a href="#var关键字" class="headerlink" title="var关键字"></a>var关键字</h4><p>JDK 10引入</p>
<p>有些时候，类型的名字太长，写起来比较麻烦。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">StringBuilder sb = <span class="keyword">new</span> StringBuilder();</span><br></pre></td></tr></table></figure>

<p>这个时候，如果想省略变量类型，可以使用<code>var</code>关键字：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> sb = <span class="keyword">new</span> StringBuilder();</span><br></pre></td></tr></table></figure>

<p>编译器会根据赋值语句<strong>自动推断</strong>出变量<code>sb</code>的类型是<code>StringBuilder</code>。对编译器来说，语句：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> sb = <span class="keyword">new</span> StringBuilder();</span><br></pre></td></tr></table></figure>

<p>实际上会自动变成：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">StringBuilder sb = <span class="keyword">new</span> StringBuilder();</span><br></pre></td></tr></table></figure>

<p>因此，使用<code>var</code>定义变量，仅仅是少写了变量类型而已。</p>
<h4 id="变量的作用范围"><a href="#变量的作用范围" class="headerlink" title="变量的作用范围"></a>变量的作用范围</h4><p>在Java中，多行语句用{ }括起来。很多控制语句，例如条件判断和循环，都以{ }作为它们自身的范围，例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (...) &#123; <span class="comment">// if开始</span></span><br><span class="line">    ...</span><br><span class="line">    <span class="keyword">while</span> (...) &#123; <span class="keyword">while</span> 开始</span><br><span class="line">        ...</span><br><span class="line">        <span class="keyword">if</span> (...) &#123; <span class="comment">// if开始</span></span><br><span class="line">            ...</span><br><span class="line">        &#125; <span class="comment">// if结束</span></span><br><span class="line">        ...</span><br><span class="line">    &#125; <span class="comment">// while结束</span></span><br><span class="line">    ...</span><br><span class="line">&#125; <span class="comment">// if结束</span></span><br></pre></td></tr></table></figure>

<p>只要正确地嵌套这些{ }，编译器就能识别出语句块的开始和结束。而在语句块中定义的变量，它有一个作用域，就是从定义处开始，到语句块结束。超出了作用域引用这些变量，编译器会报错。举个例子：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    ...</span><br><span class="line">    <span class="keyword">int</span> i = <span class="number">0</span>; <span class="comment">// 变量i从这里开始定义</span></span><br><span class="line">    ...</span><br><span class="line">    &#123;</span><br><span class="line">        ...</span><br><span class="line">        <span class="keyword">int</span> x = <span class="number">1</span>; <span class="comment">// 变量x从这里开始定义</span></span><br><span class="line">        ...</span><br><span class="line">        &#123;</span><br><span class="line">            ...</span><br><span class="line">            String s = <span class="string">"hello"</span>; <span class="comment">// 变量s从这里开始定义</span></span><br><span class="line">            ...</span><br><span class="line">        &#125; <span class="comment">// 变量s作用域到此结束</span></span><br><span class="line">        ...</span><br><span class="line">        <span class="comment">// 注意，这是一个新的变量s，它和上面的变量同名，</span></span><br><span class="line">        <span class="comment">// 但是因为作用域不同，它们是两个不同的变量:</span></span><br><span class="line">        String s = <span class="string">"hi"</span>;</span><br><span class="line">        ...</span><br><span class="line">    &#125; <span class="comment">// 变量x和s作用域到此结束</span></span><br><span class="line">    ...</span><br><span class="line">&#125; <span class="comment">// 变量i作用域到此结束</span></span><br></pre></td></tr></table></figure>

<p>定义变量时，要遵循作用域最小化原则，尽量将变量定义在尽可能小的作用域，并且，不要重复使用变量名。</p>
<h2 id="表达式和运算符"><a href="#表达式和运算符" class="headerlink" title="表达式和运算符"></a>表达式和运算符</h2><p>表达式是 Java 程序更高一级的结构。Java 解释器会求出表达式的值。最简单的表达式叫基本表达式，由字面量和变量组成。基本表达式没什么意思，使用运算符把基本表达式连在一起可以组成复杂的表达式。不过，运算符不仅能连接基本表达式，也能在任意复杂度的表达式中使用。</p>
<h3 id="运算符概述"><a href="#运算符概述" class="headerlink" title="运算符概述"></a>运算符概述</h3><p>一门编程语言能编写什么样的表达式，完全取决于可用的运算符。Java 提供了丰富的运算符，但在有效使用它们之前，要弄清两个重要的概念：优先级和结合性。</p>
<ol>
<li>优先级：优先级指定运算符执行的顺序。优先级高的运算符在优先级低的运算符之前运算。运算符默认的优先级可以使用括号改变，括号能明确指定运算的顺序。</li>
<li>结合性：结合性是运算符的一个属性，定义如何计算有歧义的表达式。如果表达式中有多个优先级相同的运算符，结合性尤其重要。大多数运算符由左至右结合，即从左向右计算。不过，赋值和一元运算符由右至左结合。</li>
</ol>
<table>
<thead>
<tr>
<th>优先级</th>
<th>结合性</th>
<th>运算符</th>
<th>操作数类型</th>
<th>执行的运算</th>
</tr>
</thead>
<tbody><tr>
<td>16</td>
<td>L</td>
<td><code>.</code></td>
<td>对象，成员</td>
<td>访问对象成员</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>[]</code></td>
<td>数组，<code>int</code></td>
<td>获取数组中的元素</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>( args )</code></td>
<td>方法，参数列表</td>
<td>调用方法</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>++</code>，<code>--</code></td>
<td>变量</td>
<td>后递增、后递减</td>
</tr>
<tr>
<td>15</td>
<td>R</td>
<td><code>++</code>，<code>--</code></td>
<td>变量</td>
<td>前递增、前递减</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>+</code>，<code>-</code></td>
<td>数字</td>
<td>正号、负号</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>~</code></td>
<td>整数</td>
<td>按位补码</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>!</code></td>
<td>布尔值</td>
<td>逻辑求反</td>
</tr>
<tr>
<td>14</td>
<td>R</td>
<td><code>new</code></td>
<td>类，参数列表</td>
<td>创建对象</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>( type )</code></td>
<td>类型，任何类型</td>
<td>校正（类型转化）</td>
</tr>
<tr>
<td>13</td>
<td>L</td>
<td><code>\*</code>，<code>/</code>，<code>%</code></td>
<td>数字，数字</td>
<td>乘法，除法，求余数</td>
</tr>
<tr>
<td>12</td>
<td>L</td>
<td><code>+</code>，<code>-</code></td>
<td>数字，数字</td>
<td>加法，减法</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>+</code></td>
<td>字符串，任何类型</td>
<td>字符串连接</td>
</tr>
<tr>
<td>11</td>
<td>L</td>
<td><code>&lt;&lt;</code></td>
<td>整数，整数</td>
<td>左移</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>&gt;&gt;</code></td>
<td>整数，整数</td>
<td>右移，高位补符号</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>&gt;&gt;&gt;</code></td>
<td>整数，整数</td>
<td>右移，高位补零</td>
</tr>
<tr>
<td>10</td>
<td>L</td>
<td><code>&lt;</code>，<code>&lt;==</code></td>
<td>数字，数字</td>
<td>小于，小于或等于</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>&gt;</code>，<code>&gt;==</code></td>
<td>数字，数字</td>
<td>大于，大于或等于</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>instanceof</code></td>
<td>引用类型，类型</td>
<td>类型比较</td>
</tr>
<tr>
<td>9</td>
<td>L</td>
<td><code>==</code></td>
<td>基本类型，基本类型</td>
<td>等于（值相同）</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>!=</code></td>
<td>基本类型，基本类型</td>
<td>不等于（值不同）</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>==</code></td>
<td>引用类型，引用类型</td>
<td>等于（指向同一个对象）</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>!=</code></td>
<td>引用类型，引用类型</td>
<td>不等于（指向不同的对象）</td>
</tr>
<tr>
<td>8</td>
<td>L</td>
<td><code>&amp;</code></td>
<td>整数，整数</td>
<td>位与</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>&amp;</code></td>
<td>布尔值，布尔值</td>
<td>逻辑与</td>
</tr>
<tr>
<td>7</td>
<td>L</td>
<td><code>^</code></td>
<td>整数，整数</td>
<td>位异或</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>^</code></td>
<td>布尔值，布尔值</td>
<td>逻辑异或</td>
</tr>
<tr>
<td>6</td>
<td>L</td>
<td>`</td>
<td>`</td>
<td>整数，整数</td>
</tr>
<tr>
<td></td>
<td></td>
<td>`</td>
<td>`</td>
<td>布尔值，布尔值</td>
</tr>
<tr>
<td>5</td>
<td>L</td>
<td><code>&amp;&amp;</code></td>
<td>布尔值，布尔值</td>
<td>条件与</td>
</tr>
<tr>
<td>4</td>
<td>L</td>
<td>`</td>
<td></td>
<td>`</td>
</tr>
<tr>
<td>3</td>
<td>R</td>
<td><code>? :</code></td>
<td>布尔值，任何类型</td>
<td>条件（三元）运算符</td>
</tr>
<tr>
<td>2</td>
<td>R</td>
<td><code>=</code></td>
<td>变量，任何类型</td>
<td>赋值</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>*=</code>，<code>/=</code>,<code>%=</code>,<code>+=</code>,<code>-=</code>，<code>&lt;&lt;=</code>，<code>&gt;&gt;=</code>，<code>&gt;&gt;&gt;=</code>,<code>&amp;=</code>，<code>^=</code>，<code>^=</code>，`</td>
<td>=`</td>
<td>变量，任何类型</td>
</tr>
<tr>
<td>1</td>
<td>R</td>
<td><code>-&gt;</code></td>
<td>参数列表，方法体</td>
<td>lambda表达式</td>
</tr>
</tbody></table>
<ul>
<li>数字：整数、浮点数或字符（即除了布尔类型之外的任何一种基本类型）。因为这些类型对应的包装类（例如 Character、Integer 和 Double）能自动拆包，所以在这些地方也能使用相应的包装类。</li>
<li>整数：byte、short、int、long 或 char 类型的值（获取数组元素的运算符 [ ] 不能使用 long 类型的值）。因为能自动拆包，所以也能使用 Byte、Short、Integer、Long 和 Character 类型的值。</li>
<li>引用类型：对象或数组。</li>
<li>变量：变量或其他符号名称（例如数组中的元素），只要能赋值就行。</li>
</ul>
<p>有些运算符只有一个操作数，这种运算符叫一元运算符。不过，大多数运算符都是二元运算符，有两个操作数。Java 还定义了一个三元运算符，经常称作条件运算符，就像是表达式中的 if 语句。它的三个操作数由问号和冒号分开，第二个和第三个操作数必须能转换成同一种类型：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">x &gt; y ? x : y  <span class="comment">// 三元表达式；计算x和y哪个大</span></span><br></pre></td></tr></table></figure>



<h3 id="算术运算符"><a href="#算术运算符" class="headerlink" title="算术运算符"></a>算术运算符</h3><p>Java的基本算术运算符与其他大多数程序设计语言是相同的。其中包括加号（<code>+</code>）、减号（<code>-</code>）、除号（<code>/</code>）、乘号（<code>*</code>）以及模数（<code>%</code>，从整数除法中获得余数）。</p>
<blockquote>
<p>整数除法会直接砍掉小数，而不是进位。</p>
</blockquote>
<p>Java也用一种简写形式进行运算，并同时进行赋值操作。这是由等号前的一个运算符标记的，而且对于语言中的所有运算符都是固定的。例如，为了将4加到变量x，并将结果赋给x，可用：<code>x+=4</code>。</p>
<h4 id="整数运算"><a href="#整数运算" class="headerlink" title="整数运算"></a>整数运算</h4><p> Java的整数运算遵循四则运算规则，可以使用任意嵌套的小括号。四则运算规则和初等数学一致。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> i = (<span class="number">100</span> + <span class="number">200</span>) * (<span class="number">99</span> - <span class="number">88</span>); <span class="comment">// 3300</span></span><br><span class="line">        <span class="keyword">int</span> n = <span class="number">7</span> * (<span class="number">5</span> + (i - <span class="number">9</span>)); <span class="comment">// 23072</span></span><br><span class="line">        System.out.println(i);</span><br><span class="line">        System.out.println(n);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>整数的数值表示不但是精确的，而且整数运算永远是精确的，即使是除法也是精确的，因为两个整数相除只能得到结果的整数部分：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> x = <span class="number">12345</span> / <span class="number">67</span>; <span class="comment">// 184</span></span><br></pre></td></tr></table></figure>

<p>求余运算使用<code>%</code>：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> y = <span class="number">12345</span> % <span class="number">67</span>; <span class="comment">// 12345÷67的余数是17</span></span><br></pre></td></tr></table></figure>

<p>特别注意：整数的除法对于除数为0时运行时将报错，但编译不会报错。</p>
<h4 id="溢出"><a href="#溢出" class="headerlink" title="溢出"></a>溢出</h4><p>要特别注意，整数由于存在范围限制，如果计算结果超出了范围，就会产生溢出，而溢出<strong>不会出错</strong>，却会得到一个奇怪的结果：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> x = <span class="number">2147483640</span>;</span><br><span class="line">        <span class="keyword">int</span> y = <span class="number">15</span>;</span><br><span class="line">        <span class="keyword">int</span> sum = x + y;</span><br><span class="line">        System.out.println(sum); <span class="comment">// -2147483641</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>要解释上述结果，我们把整数<code>2147483640</code>和<code>15</code>换成二进制做加法：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">  0111 1111 1111 1111 1111 1111 1111 1000</span><br><span class="line">+ 0000 0000 0000 0000 0000 0000 0000 1111</span><br><span class="line">-----------------------------------------</span><br><span class="line">  1000 0000 0000 0000 0000 0000 0000 0111</span><br></pre></td></tr></table></figure>

<p>由于最高位计算结果为<code>1</code>，因此，加法结果变成了一个负数。</p>
<p>要解决上面的问题，可以把<code>int</code>换成<code>long</code>类型，由于<code>long</code>可表示的整型范围更大，所以结果就不会溢出：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">long</span> x = <span class="number">2147483640</span>;</span><br><span class="line"><span class="keyword">long</span> y = <span class="number">15</span>;</span><br><span class="line"><span class="keyword">long</span> sum = x + y;</span><br><span class="line">System.out.println(sum); <span class="comment">// 2147483655</span></span><br></pre></td></tr></table></figure>

<p>还有一种简写的运算符，即<code>+=</code>，<code>-=</code>，<code>*=</code>，<code>/=</code>，同Python，它们的使用方法如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">n += <span class="number">100</span>; <span class="comment">// 3409, 相当于 n = n + 100;</span></span><br><span class="line">n -= <span class="number">100</span>; <span class="comment">// 3309, 相当于 n = n - 100;</span></span><br></pre></td></tr></table></figure>

<h3 id="字符串连接运算符"><a href="#字符串连接运算符" class="headerlink" title="字符串连接运算符"></a>字符串连接运算符</h3><p><code>+</code>号（以及相关的 <code>+=</code> 运算符）除了能计算数字之和以外，还能连接字符串。如果 <code>+</code> 号的两个操作数中有一个是字符串，另一个操作数也会转换成字符串。</p>
<p>因此，如果加法和字符串连接结合在一起使用，要把加法表达式放在括号中。如果不这么做，加号会被理解成连接运算符。</p>
<p>Java 解释器原生支持把所有基本类型转换成字符串。对象转换成字符串时，调用的是对象的 <code>toString()</code> 方法。有些类自定义了 <code>toString()</code> 方法，所以这些类的对象可以使用这种方式轻易地转换成字符串。数组转换成字符串时会调用原生的 <code>toString()</code> 方法，不过可惜，这个方法没有为数组的内容提供有用的字符串形式。</p>
<h3 id="递增和递减运算符"><a href="#递增和递减运算符" class="headerlink" title="递增和递减运算符"></a>递增和递减运算符</h3><p>Java还提供了<code>++</code>运算和<code>--</code>运算，它们可以对一个整数进行加1和减1的操作：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = <span class="number">3300</span>;</span><br><span class="line">        n++; <span class="comment">// 3301, 相当于 n = n + 1;</span></span><br><span class="line">        n--; <span class="comment">// 3300, 相当于 n = n - 1;</span></span><br><span class="line">        <span class="keyword">int</span> y = <span class="number">100</span> + (++n); <span class="comment">// 不要这么写</span></span><br><span class="line">        System.out.println(y);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><code>++</code> 运算符把它的单个操作数增加 1，这个操作数必须是变量、数组中的元素或对象的字段。</p>
<p>这个运算符的行为取决于它相对于操作数的位置。<code>++n</code>表示先加1再引用n，<code>n++</code>表示先引用n再加1。</p>
<ul>
<li><p>放在操作数之前，是前递增运算符，递增操作数的值，并返回递增后的值。</p>
</li>
<li><p>放在操作数之后，是后递增运算符，递增操作数的值，但返回递增前的值。</p>
</li>
</ul>
<p>表达式 <code>x++</code> 和 <code>x--</code> 分别等效于 <code>x=x+1</code> 和 <code>x=x-1</code>，不过使用递增和递减运算符时，只会计算一次 x 的值。如果 x 是有副作用的表达式，情况就大不相同了。例如，下面两个表达式不等效：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">a[i++]++;             <span class="comment">// 递增数组中的一个元素 </span></span><br><span class="line">a[i++] = a[i++] + <span class="number">1</span>;  <span class="comment">// 把数组中的一个元素增加1，然后把新值存储在另一个元素中</span></span><br></pre></td></tr></table></figure>

<p>这些运算符，不管放在前面还是后面，最常用来递增或递减控制循环的计数器。</p>
<h3 id="比较运算符"><a href="#比较运算符" class="headerlink" title="比较运算符"></a>比较运算符</h3><p>比较运算符包括测试两个值是否相等的相等运算符和测试有序类型（数字和字符）数据之间大小关系的关系运算符。这两种运算符计算的结果都是布尔值，因此一般用于 if 语句、while 和 for 循环，作为分支和循环的判定条件。</p>
<p>Java 提供了下述相等运算符。</p>
<ul>
<li>等于（<code>==</code>）：如果 <code>==</code> 运算符的两个操作数相等，计算结果为 true；否则计算结果为 false。<ul>
<li>如果操作数是基本类型，这个运算符测试两个操作数的值是否一样。</li>
<li>如果操作数是引用类型，这个运算符测试两个操作数是否指向同一个对象或数组。</li>
<li>尤其要注意，这个运算符不能测试两个字符串是否相等。</li>
<li>如果使用 <code>==</code> 比较两个数字或字符，而且两个操作数的类型不同，在比较之前会把取值范围窄的操作数转换成取值范围宽的操作数类型。例如，比较 short 类型的值和 float类型的值时，在比较之前会先把 short 类型的值转换成 float 类型。</li>
<li>对浮点数来说，特殊的负零和普通的正零相等；特殊的 NaN 和任何数，包括 NaN 自己，都不相等。如果想测试浮点数是否为 NaN，要使用 <code>Float.isNan()</code> 或 <code>Double.isNan()</code> 方法。</li>
</ul>
</li>
<li>不等于（<code>!=</code>）：<code>!=</code> 运算符完全是 <code>==</code> 运算符的反运算。如果两个基本类型操作数的值不同，或者两个引用类型操作数指向不同的对象或数组，<code>!=</code> 运算符的计算结果为 true；否则，计算结果为 false。</li>
</ul>
<p>关系运算符可用于数字和字符，但不能用于布尔值、对象和数组，因为这些类型无序。Java 提供了下述关系运算符：</p>
<ul>
<li>小于（<code>&lt;</code>）：如果第一个操作数小于第二个操作数，计算结果为 true。 </li>
<li>小于或等于（<code>&lt;=</code>）：如果第一个操作数小于或等于第二个操作数，计算结果为 true。</li>
<li>大于（<code>&gt;</code>）：如果第一个操作数大于第二个操作数，计算结果为 true。</li>
<li>大于或等于（<code>&gt;=</code>）：如果第一个操作数大于或等于第二个操作数，计算结果为 true。</li>
</ul>
<h3 id="逻辑运算符"><a href="#逻辑运算符" class="headerlink" title="逻辑运算符"></a>逻辑运算符</h3><p>逻辑运算符的操作数必须是布尔值，而且计算结果也是布尔值，对于布尔类型<code>boolean</code>，永远只有<code>true</code>和<code>false</code>两个值。</p>
<table>
<thead>
<tr>
<th>a</th>
<th>b</th>
<th>a&amp;b</th>
<th>a&amp;&amp;b</th>
<th>a|b</th>
<th>a||b</th>
<th>!a</th>
<th>a^b</th>
</tr>
</thead>
<tbody><tr>
<td>true</td>
<td>true</td>
<td>true</td>
<td>true</td>
<td>true</td>
<td>true</td>
<td>false</td>
<td>false</td>
</tr>
<tr>
<td>true</td>
<td>false</td>
<td>false</td>
<td>false</td>
<td>true</td>
<td>true</td>
<td>false</td>
<td>true</td>
</tr>
<tr>
<td>false</td>
<td>true</td>
<td>false</td>
<td>false</td>
<td>true</td>
<td>true</td>
<td>true</td>
<td>true</td>
</tr>
<tr>
<td>false</td>
<td>false</td>
<td>false</td>
<td>false</td>
<td>false</td>
<td>false</td>
<td>true</td>
<td>false</td>
</tr>
</tbody></table>
<h4 id="条件与（-amp-amp-）"><a href="#条件与（-amp-amp-）" class="headerlink" title="条件与（&amp;&amp;）"></a>条件与（<code>&amp;&amp;</code>）</h4><p>这个运算符对操作数执行逻辑与运算。</p>
<ul>
<li>仅当两个操作数都是 true 时才返回 true；</li>
<li>如果有一个或两个操作数都是 false，计算结果为 false。</li>
</ul>
<p>这个运算符之所以叫条件与，是因为它会视情况决定是否计算第二个操作数。如果第一个操作数的结算结果为 false，不管第二个操作数的计算结果是什么，这个表达式的计算结果都是 false。因此，为了提高效率，Java 解释器会走捷径，跳过第二个操作数。（短路运算）因为不一定会计算第二个操作数，所以使用这个运算符时，如果表达式有副作用，一定要注意。类似的，对于<code>||</code>运算，只要能确定第一个值为<code>true</code>，后续计算也不再进行，而是直接返回<code>true</code>，不过，因为有这种特性，可以使用这个运算符编写如下的 Java 表达式：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (data != <span class="keyword">null</span> &amp;&amp; i &lt; data.length &amp;&amp; data[i] != -<span class="number">1</span>) &#123;</span><br><span class="line">    <span class="comment">//...</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>如果第一个和第二个比较表达式的计算结果为 false，第二个和第三个比较表达式会导致错误。幸好，我们无需为此担心，因为 <code>&amp;&amp;</code> 运算符会视情况决定是否执行后面的表达式。</p>
<h4 id="条件或（-）"><a href="#条件或（-）" class="headerlink" title="条件或（||）"></a>条件或（<code>||</code>）</h4><p>这个运算符在两个布尔值操作数上执行逻辑或运算。如果其中一个或两个都是 true，计算结果为 true；如果两个操作数都是 false，计算结果为 false。</p>
<p>和 <code>&amp;&amp;</code> 运算符一样，<code>||</code> 并不总会计算第二个操作数。如果第一个操作数的计算结果为 true，不管第二个操作数的计算结果是什么，表达式的计算结果都是 true。因此，遇到这种情况时，<code>||</code> 运算符会跳过第二个操作数。</p>
<h4 id="逻辑非（-）"><a href="#逻辑非（-）" class="headerlink" title="逻辑非（!）"></a>逻辑非（<code>!</code>）</h4><p>这个运算符改变操作数的布尔值。如果应用于 true，计算结果为 false；如果应用于false，计算结果为 true。</p>
<p>在下面这种表达式中很有用：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (!found) ...          <span class="comment">// found是其他地方定义的布尔值 </span></span><br><span class="line"><span class="keyword">while</span> (!c.isEmpty()) ... <span class="comment">// isEmpty()方法返回布尔值</span></span><br></pre></td></tr></table></figure>

<p><code>!</code> 是一元运算符，优先级高，经常必须使用括号：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (!(x &gt; y &amp;&amp; y &gt; z))</span><br></pre></td></tr></table></figure>

<h4 id="逻辑与（-amp-）"><a href="#逻辑与（-amp-）" class="headerlink" title="逻辑与（&amp;）"></a>逻辑与（<code>&amp;</code>）</h4><p>如果操作数是布尔值，<code>&amp;</code> 运算符的行为和 <code>&amp;&amp;</code> 运算符类似，但是不管第一个操作数的计算结果如何，总会计算第二个操作数。不过，这个运算符几乎都用作位运算符，处理整数操作数。很多 Java 程序员都认为使用这个运算符处理布尔值操作数是不合法的 Java代码。</p>
<h4 id="逻辑或（-）"><a href="#逻辑或（-）" class="headerlink" title="逻辑或（|）"></a>逻辑或（<code>|</code>）</h4><p>这个运算符在两个布尔值操作数上执行逻辑或运算，和 <code>||</code> 运算符类似，但是就算第一个操作数的计算结果为 true，也会计算第二个操作数。<code>|</code> 运算符几乎都用作位运算符，处理整数操作数，很少用来处理布尔值操作数。</p>
<h4 id="逻辑异或（-）"><a href="#逻辑异或（-）" class="headerlink" title="逻辑异或（^）"></a>逻辑异或（<code>^</code>）</h4><p>如果操作数是布尔值，这个运算符的计算结果是两个操作数的异或。如果两个操作数中只有一个是 true，计算结果才是 true。也就是说，如果两个操作数都是 true 或 false，计算结果为 false。</p>
<p>这个运算符与 <code>&amp;&amp;</code> 和 <code>||</code> 不同，始终会计算两个操作数。<code>^</code> 运算符更常用作位运算符，处理整数操作数。如果操作数是布尔值，这个运算符等效于 <code>!=</code> 运算符。</p>
<h3 id="位运算符和位移运算符"><a href="#位运算符和位移运算符" class="headerlink" title="位运算符和位移运算符"></a>位运算符和位移运算符</h3><p>位运算符和位移运算符是低层运算符，处理组成整数的单个位。现代 Java 程序很少使用位运算符，除非处理低层操作（例如网络编程）。这两种运算符用于测试和设定整数中的单个标志位。若想理解这些运算符的行为，必须先理解二进制数以及用于表示负整数的二进制补码方式。</p>
<p>在计算机中，整数总是以二进制的形式表示。例如，<code>int</code>类型的整数<code>7</code>使用4字节表示的二进制如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">00000000 0000000 0000000 00000111</span><br></pre></td></tr></table></figure>

<p>可以对整数进行移位运算。对整数<code>7</code>左移1位将得到整数<code>14</code>，左移两位将得到整数<code>28</code>：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> n = <span class="number">7</span>;       <span class="comment">// 00000000 00000000 00000000 00000111 = 7</span></span><br><span class="line"><span class="keyword">int</span> a = n &lt;&lt; <span class="number">1</span>;  <span class="comment">// 00000000 00000000 00000000 00001110 = 14</span></span><br><span class="line"><span class="keyword">int</span> b = n &lt;&lt; <span class="number">2</span>;  <span class="comment">// 00000000 00000000 00000000 00011100 = 28</span></span><br><span class="line"><span class="keyword">int</span> c = n &lt;&lt; <span class="number">28</span>; <span class="comment">// 01110000 00000000 00000000 00000000 = 1879048192</span></span><br><span class="line"><span class="keyword">int</span> d = n &lt;&lt; <span class="number">29</span>; <span class="comment">// 11100000 00000000 00000000 00000000 = -536870912</span></span><br></pre></td></tr></table></figure>

<p>左移29位时，由于最高位变成<code>1</code>，因此结果变成了负数。</p>
<p>类似的，对整数进行右移，结果如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> n = <span class="number">7</span>;       <span class="comment">// 00000000 00000000 00000000 00000111 = 7</span></span><br><span class="line"><span class="keyword">int</span> a = n &gt;&gt; <span class="number">1</span>;  <span class="comment">// 00000000 00000000 00000000 00000011 = 3</span></span><br><span class="line"><span class="keyword">int</span> b = n &gt;&gt; <span class="number">2</span>;  <span class="comment">// 00000000 00000000 00000000 00000001 = 1</span></span><br><span class="line"><span class="keyword">int</span> c = n &gt;&gt; <span class="number">3</span>;  <span class="comment">// 00000000 00000000 00000000 00000000 = 0</span></span><br></pre></td></tr></table></figure>

<p>如果对一个负数进行右移，最高位的<code>1</code>不动，结果仍然是一个负数：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> n = -<span class="number">536870912</span>;</span><br><span class="line"><span class="keyword">int</span> a = n &gt;&gt; <span class="number">1</span>;  <span class="comment">// 11110000 00000000 00000000 00000000 = -268435456</span></span><br><span class="line"><span class="keyword">int</span> b = n &gt;&gt; <span class="number">2</span>;  <span class="comment">// 10111000 00000000 00000000 00000000 = -134217728</span></span><br><span class="line"><span class="keyword">int</span> c = n &gt;&gt; <span class="number">28</span>; <span class="comment">// 11111111 11111111 11111111 11111110 = -2</span></span><br><span class="line"><span class="keyword">int</span> d = n &gt;&gt; <span class="number">29</span>; <span class="comment">// 11111111 11111111 11111111 11111111 = -1</span></span><br></pre></td></tr></table></figure>

<p>还有一种不带符号的右移运算，使用<code>&gt;&gt;&gt;</code>，它的特点是符号位跟着动，因此，对一个负数进行<code>&gt;&gt;&gt;</code>右移，它会变成正数，原因是最高位的<code>1</code>变成了<code>0</code>：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> n = -<span class="number">536870912</span>;</span><br><span class="line"><span class="keyword">int</span> a = n &gt;&gt;&gt; <span class="number">1</span>;  <span class="comment">// 01110000 00000000 00000000 00000000 = 1879048192</span></span><br><span class="line"><span class="keyword">int</span> b = n &gt;&gt;&gt; <span class="number">2</span>;  <span class="comment">// 00111000 00000000 00000000 00000000 = 939524096</span></span><br><span class="line"><span class="keyword">int</span> c = n &gt;&gt;&gt; <span class="number">29</span>; <span class="comment">// 00000000 00000000 00000000 00000111 = 7</span></span><br><span class="line"><span class="keyword">int</span> d = n &gt;&gt;&gt; <span class="number">31</span>; <span class="comment">// 00000000 00000000 00000000 00000001 = 1</span></span><br></pre></td></tr></table></figure>

<p>对<code>byte</code>和<code>short</code>类型进行移位时，会首先转换为<code>int</code>再进行位移。</p>
<p>仔细观察可发现，左移实际上就是不断地×2，右移实际上就是不断地÷2。</p>
<hr>
<ul>
<li><p>如果位运算符的操作数中有一个是 long 类型，结果就是 long 类型。除此之外，结果都是int 类型。</p>
</li>
<li><p>如果位移运算符左边的操作数是 long 类型，结果为 long 类型；否则，结果是int 类型。</p>
</li>
</ul>
<h4 id="按位补码（-）"><a href="#按位补码（-）" class="headerlink" title="按位补码（~）"></a>按位补码（<code>~</code>）</h4><p>一元运算符 <code>~</code> 是按位补码运算符，或叫位或运算符。它把单个操作数的每一位反相，1 变成 0，0 变成 1。</p>
<p>非运算的规则是，<code>0</code>和<code>1</code>互换：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">n = ~<span class="number">0</span>; <span class="comment">// 1</span></span><br><span class="line">n = ~<span class="number">1</span>; <span class="comment">// 0</span></span><br></pre></td></tr></table></figure>

<h4 id="位与（-amp-）"><a href="#位与（-amp-）" class="headerlink" title="位与（&amp;）"></a>位与（<code>&amp;</code>）</h4><p>与运算的规则是，必须两个数同时为<code>1</code>，结果才为<code>1</code>：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">n = <span class="number">0</span> &amp; <span class="number">0</span>; <span class="comment">// 0</span></span><br><span class="line">n = <span class="number">0</span> &amp; <span class="number">1</span>; <span class="comment">// 0</span></span><br><span class="line">n = <span class="number">1</span> &amp; <span class="number">0</span>; <span class="comment">// 0</span></span><br><span class="line">n = <span class="number">1</span> &amp; <span class="number">1</span>; <span class="comment">// 1</span></span><br></pre></td></tr></table></figure>

<h4 id="位或（-）"><a href="#位或（-）" class="headerlink" title="位或（|）"></a>位或（<code>|</code>）</h4><p>或运算的规则是，只要任意一个为<code>1</code>，结果就为<code>1</code>：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">n = <span class="number">0</span> | <span class="number">0</span>; <span class="comment">// 0</span></span><br><span class="line">n = <span class="number">0</span> | <span class="number">1</span>; <span class="comment">// 1</span></span><br><span class="line">n = <span class="number">1</span> | <span class="number">0</span>; <span class="comment">// 1</span></span><br><span class="line">n = <span class="number">1</span> | <span class="number">1</span>; <span class="comment">// 1</span></span><br></pre></td></tr></table></figure>

<h4 id="位异或（-）"><a href="#位异或（-）" class="headerlink" title="位异或（^）"></a>位异或（<code>^</code>）</h4><p>异或运算的规则是，如果两个数不同，结果为<code>1</code>，否则为<code>0</code>：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">n = <span class="number">0</span> ^ <span class="number">0</span>; <span class="comment">// 0</span></span><br><span class="line">n = <span class="number">0</span> ^ <span class="number">1</span>; <span class="comment">// 1</span></span><br><span class="line">n = <span class="number">1</span> ^ <span class="number">0</span>; <span class="comment">// 1</span></span><br><span class="line">n = <span class="number">1</span> ^ <span class="number">1</span>; <span class="comment">// 0</span></span><br></pre></td></tr></table></figure>

<p>对两个整数进行位运算，实际上就是按位对齐，然后依次对每一位进行运算。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> i = <span class="number">167776589</span>; <span class="comment">// 00001010 00000000 00010001 01001101</span></span><br><span class="line">        <span class="keyword">int</span> n = <span class="number">167776512</span>; <span class="comment">// 00001010 00000000 00010001 00000000</span></span><br><span class="line">        System.out.println(i &amp; n); <span class="comment">// 167776512</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p> 上述按位与运算实际上可以看作两个整数表示的IP地址<code>10.0.17.77</code>和<code>10.0.17.0</code>，通过与运算，可以快速判断一个IP是否在给定的网段内。</p>
<h4 id="左移（-lt-lt-）"><a href="#左移（-lt-lt-）" class="headerlink" title="左移（&lt;&lt;）"></a>左移（<code>&lt;&lt;</code>）</h4><p><code>&lt;&lt;</code> 运算符把左侧操作数的每一位向左移动右侧操作数指定的位数。左侧操作数的高位被丢掉，右边缺少的位补零。整数向左移 n 位，相当于乘于 2<sup>n</sup>。</p>
<ul>
<li>如果左侧操作数是 long 类型，右侧操作数应该介于 0 和 63 之间。</li>
<li>如果左侧操作数是 int 类型，右侧操作数应该介于 0 和 31 之间。</li>
</ul>
<h4 id="带符号右移（-gt-gt-）"><a href="#带符号右移（-gt-gt-）" class="headerlink" title="带符号右移（&gt;&gt;）"></a>带符号右移（<code>&gt;&gt;</code>）</h4><p><code>&gt;&gt;</code>运算符把左侧操作数的每一位向右移动右侧操作数指定的位数。左侧操作符的低位被移除，移入的高位和原来的最高位一样。也就是说，如果左侧操作数是正数，移入的高位是 0；如果左侧操作数是负数，移入的高位是 1。这种技术叫高位补符号，作用是保留左侧操作数的符号。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">10</span> &gt;&gt; <span class="number">1</span>     <span class="comment">// 00001010 &gt;&gt; 1 = 00000101 = 5 = 10/2 </span></span><br><span class="line"><span class="number">27</span> &gt;&gt; <span class="number">3</span>     <span class="comment">// 00011011 &gt;&gt; 3 = 00000011 = 3 = 27/8 </span></span><br><span class="line">-<span class="number">50</span> &gt;&gt; <span class="number">2</span>    <span class="comment">// 11001110 &gt;&gt; 2 = 11110011 = -13 != -50/4</span></span><br></pre></td></tr></table></figure>


<p>如果左侧操作数是正数，右侧操作数是 n，<code>&gt;&gt;</code> 运算符的计算结果相当于整数除以 2<sup>n</sup>。</p>
<h4 id="不带符号右移（-gt-gt-gt-）"><a href="#不带符号右移（-gt-gt-gt-）" class="headerlink" title="不带符号右移（&gt;&gt;&gt;）"></a>不带符号右移（<code>&gt;&gt;&gt;</code>）</h4><p>这个运算符和 <code>&gt;&gt;</code> 类似，但是不管左侧操作数的符号是什么，高位总是移入 0。这种技术叫高位补零。左侧操作数是无符号的数字时才适用这个运算符（可是 Java 的整数类型都带符号）。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">0xff</span> &gt;&gt;&gt; <span class="number">4</span>     <span class="comment">// 11111111 &gt;&gt;&gt; 4 = 00001111 = 15 = 255/16 </span></span><br><span class="line">-<span class="number">50</span> &gt;&gt;&gt; <span class="number">2</span>     <span class="comment">// 0xFFFFFFCE &gt;&gt;&gt; 2 = 0x3FFFFFF3 = 1073741811</span></span><br></pre></td></tr></table></figure>

<h3 id="赋值运算符"><a href="#赋值运算符" class="headerlink" title="赋值运算符"></a>赋值运算符</h3><p>赋值运算符把值存储在某种变量中或赋予某种变量。左侧操作数必须是适当的局部变量、数组元素或对象字段。右侧操作数可以是与变量兼容的任何类型。赋值表达式的计算结果是赋予变量的值。不过，更重要的是，赋值表达式的副作用是执行赋值操作。和其他二运算符不同的是，赋值运算符是右结合的，也就是说，赋值表达式 a=b=c 从右向左执行，即 a=(b=c)。</p>
<p>除了这个简单的赋值运算符之外，Java 还定义了另外 11 个运算符，其中 5 个与算术运算符一起使用，6 个与位运算符和位移运算符一起使用。例如，<code>+=</code> 运算符先读取左侧变量的值，再和右侧操作数相加。这种表达式的副作用是把两数之和赋值给左侧变量，返回值也是两数之和。因此，表达式 <code>x+=2</code> 几乎和 <code>x=x+2</code> 一样。这两种表达式之间的区别是，<code>+=</code> 运算符只会计算一次左侧操作数。如果左侧操作数有副作用，这个区别就体现出来了。</p>
<h3 id="条件运算符"><a href="#条件运算符" class="headerlink" title="条件运算符"></a>条件运算符</h3><p>条件运算符 <code>?:</code> 是有点晦涩的三元运算符（有三个操作数），从 C 语言继承而来，可以在一个表达式中嵌入条件判断。这个运算符可以看成是 if/else 语句的运算符版。条件运算符的第一个和第二个操作数使用问号（<code>?</code>）分开，第二个和第三个操作数使用冒号（<code>:</code>）分开。</p>
<p>第一个操作数的计算结果必须是布尔值。第二个和第三个操作数可以是任意类型，但要能转换成同一类型。</p>
<p>条件运算符先计算第一个操作数，如果结果为 true，就计算第二个操作数，并把结果当成表达式的返回值；如果第一个操作数的计算结果为 false，条件运算符会计算并返回第三个操作数。</p>
<p>条件运算符绝不会同时计算第二个和第三个操作数，所以使用有副作用的表达式时要小心。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = -<span class="number">100</span>;</span><br><span class="line">        <span class="keyword">int</span> x = n &gt;= <span class="number">0</span> ? n : -n;</span><br><span class="line">        System.out.println(x);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>上述语句的意思是，判断<code>n &gt;= 0</code>是否成立，如果为<code>true</code>，则返回<code>n</code>，否则返回<code>-n</code>。这实际上是一个求绝对值的表达式。</p>
<p>注意到三元运算<code>b ? x : y</code>会首先计算<code>b</code>，如果<code>b</code>为<code>true</code>，则只计算<code>x</code>，否则，只计算<code>y</code>。此外，<code>x</code>和<code>y</code>的类型必须相同，因为返回值不是<code>boolean</code>，而是<code>x</code>和<code>y</code>之一。</p>
<p>注意，<code>?:</code> 运算符的优先级只比赋值运算符高，比其他运算符都低，所以一般不用把操作数放在括号里。不过，很多程序员觉得，把第一个操作数放在括号里，条件表达式更易读。的确，毕竟 if 语句的条件表达式都放在括号里。</p>
<h3 id="instanceof操作符"><a href="#instanceof操作符" class="headerlink" title="instanceof操作符"></a><code>instanceof</code>操作符</h3><p><code>instanceof</code> 操作符的左侧操作数是对象或数组，右侧操作数是引用类型的名称。</p>
<ul>
<li>如果对象或数组是指定类型的实例，计算结果为 true；否则，计算结果为 false。</li>
<li>如果左侧操作数是 null，<code>instanceof</code> 操作符的计算结果始终为 false。</li>
<li>如果 <code>instanceof</code> 表达式的计算结果为 true，意味着可以放心校正并把左侧操作数赋值给类型为右侧操作数的变量。</li>
</ul>
<p><code>instanceof</code> 操作符只能用于引用类型和对象，不能用于基本类型和值。<code>instanceof</code> 操作符的使用示例如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// true：所有字符串都是String类的实例 </span></span><br><span class="line"><span class="string">"string"</span> <span class="keyword">instanceof</span> String </span><br><span class="line"><span class="comment">// true：字符串也是Object类的实例 </span></span><br><span class="line"><span class="string">""</span> <span class="keyword">instanceof</span> Object </span><br><span class="line"><span class="comment">// false：null不是任何类的实例 </span></span><br><span class="line"><span class="keyword">null</span> <span class="keyword">instanceof</span> String </span><br><span class="line"></span><br><span class="line">Object o = <span class="keyword">new</span> <span class="keyword">int</span>[] &#123;<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>&#125;; </span><br><span class="line">o <span class="keyword">instanceof</span> <span class="keyword">int</span>[]   <span class="comment">// true：这个数组是int数组 </span></span><br><span class="line">o <span class="keyword">instanceof</span> <span class="keyword">byte</span>[]  <span class="comment">// false：这个数组不是byte数组 </span></span><br><span class="line">o <span class="keyword">instanceof</span> Object  <span class="comment">// true：所有数组都是Object类的实例 </span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用instanceof确保能放心校正对象 </span></span><br><span class="line"><span class="keyword">if</span> (object <span class="keyword">instanceof</span> Point) &#123; </span><br><span class="line">   Point p = (Point) object; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="特殊运算符"><a href="#特殊运算符" class="headerlink" title="特殊运算符"></a>特殊运算符</h3><p>Java 有六种语言结构，有时当成运算符，有时只当成基本句法的一部分。</p>
<p><strong>1、访问对象成员（<code>.</code>）</strong>：对象由一些数据和处理这些数据的方法组成。对象的数据字段和方法称为这个对象的成员。点号运算符（<code>.</code>）用来访问这些成员。</p>
<ul>
<li>如果 <code>o</code> 是一个表达式，而且计算结果为对象引用，<code>f</code> 是这个对象的字段名称，那么，<code>o.f</code> 的计算结果是字段 <code>f</code> 中的值。</li>
<li>如果 <code>m</code> 是一个方法的名称，那么，<code>o.m</code> 指向这个方法，而且能使用后面介绍的 <code>()</code> 运算符调用。</li>
</ul>
<p><strong>2、访问数组中的元素（<code>[]</code>）</strong>：数组是由编号的值组成的列表。数组中的每个元素都能使用各自的编号（或叫索引）引用。<code>[ ]</code> 运算符能指向数组中的单个元素。如果 <code>a</code> 是一个数组，<code>i</code> 是能计算为 int 类型的表达式，那么，<code>a[i]</code> 指向 a 中的一个元素。这个运算符不像其他处理整数的运算符，它强制要求数组的索引必须是 int 类型或者取值范围更窄的类型。</p>
<p><strong>3、调用方法（<code>()</code>）</strong>：方法是一些有名称的 Java 代码，在这个名称的后面加上括号，并在括号中放零个或多个以逗号分隔的表达式，可以运行（或叫调用）方法。括号中的表达式计算得到的值是方法的参数。方法会处理这些参数，有时还会返回一个值，这个值是方法调用表达式的返回值。</p>
<ul>
<li>如果 <code>o.m</code> 是一个没有参数的方法，那么这个方法可以使用 <code>o.m()</code> 调用。</li>
<li>假设这个方法有三个参数，那么可以使用表达式 <code>o.m(x,y,z)</code> 调用。Java 解释器调用方法之前，会先计算传入的参数。这些表达式始终从左至右计算（如果参数有副作用，就能体现顺序的重要性）。</li>
</ul>
<p><strong>4、lambda表达式</strong>（<code>-&gt;</code>）：lambda 表达式是一些匿名的 Java 可执行代码，其实就是方法的主体，由方法的参数列表（零个或多个以逗号分隔的表达式，放在括号中）、lambda 箭头运算符和一段 Java 代码组成。如果代码段只有一个语句，可以省略标识块边界常用的花括号。</p>
<p><strong>5、创建对象（<code>new</code>）</strong>：在 Java 中，对象和数组使用 new 运算符创建。运算符后面跟着想创建的对象类型，括号中还可以指定一些传给对象构造方法的参数。构造方法是一种特殊的代码块，用于实例化新建的对象。创建对象的句法和调用方法的句法类似。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">new</span> ArrayList(); </span><br><span class="line"><span class="keyword">new</span> Point(<span class="number">1</span>,<span class="number">2</span>)</span><br></pre></td></tr></table></figure>

<p><strong>6、类型转换或校正（<code>()</code>）</strong>：前面已经介绍过，括号还可以当成执行缩小类型转换（或叫校正）的运算符。这个运算符的第一个操作数是想转换的类型，放在括号里；第二个操作数是要转换的值，跟在括号后面。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">(<span class="keyword">byte</span>) <span class="number">28</span>           <span class="comment">// 把整数字面量校正成byte类型 </span></span><br><span class="line">(<span class="keyword">int</span>) (x + <span class="number">3.14f</span>)   <span class="comment">// 把浮点数之和校正成整数 </span></span><br><span class="line">(String)h.get(k)    <span class="comment">// 把泛型对象校正成字符串</span></span><br></pre></td></tr></table></figure>

<h3 id="其他运算"><a href="#其他运算" class="headerlink" title="其他运算"></a>其他运算</h3><h4 id="类型自动提升与强制转型"><a href="#类型自动提升与强制转型" class="headerlink" title="类型自动提升与强制转型"></a>类型自动提升与强制转型</h4><p>在运算过程中，如果参与运算的两个数类型不一致，那么计算结果为较大类型的整型。例如，<code>short</code>和<code>int</code>计算，结果总是<code>int</code>，原因是<code>short</code>首先自动被转型为<code>int</code>：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">short</span> s = <span class="number">1234</span>;</span><br><span class="line">        <span class="keyword">int</span> i = <span class="number">123456</span>;</span><br><span class="line">        <span class="keyword">int</span> x = s + i; <span class="comment">// s自动转型为int</span></span><br><span class="line">        <span class="keyword">short</span> y = s + i; <span class="comment">// 编译错误!</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>也可以将结果强制转型，即将大范围的整数转型为小范围的整数。强制转型使用<code>(类型)</code>，例如，将<code>int</code>强制转型为<code>short</code>：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> i = <span class="number">12345</span>;</span><br><span class="line"><span class="keyword">short</span> s = (<span class="keyword">short</span>) i; <span class="comment">// 12345</span></span><br></pre></td></tr></table></figure>

<p>要注意，超出范围的强制转型会得到错误的结果，原因是转型时，<code>int</code>的两个高位字节直接被扔掉，仅保留了低位的两个字节：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> i1 = <span class="number">1234567</span>;</span><br><span class="line">        <span class="keyword">short</span> s1 = (<span class="keyword">short</span>) i1; <span class="comment">// -10617</span></span><br><span class="line">        System.out.println(s1);</span><br><span class="line">        <span class="keyword">int</span> i2 = <span class="number">12345678</span>;</span><br><span class="line">        <span class="keyword">short</span> s2 = (<span class="keyword">short</span>) i2; <span class="comment">// 24910</span></span><br><span class="line">        System.out.println(s2);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p> 因此，强制转型的结果很可能是错的。</p>
<h4 id="浮点数的运算"><a href="#浮点数的运算" class="headerlink" title="浮点数的运算"></a>浮点数的运算</h4><p> 浮点数运算和整数运算相比，只能进行加减乘除这些数值计算，不能做位运算和移位运算。</p>
<p>在计算机中，浮点数虽然表示的范围大，但是，浮点数有个非常重要的特点，就是浮点数常常无法精确表示。</p>
<p>举个栗子：</p>
<p>浮点数<code>0.1</code>在计算机中就无法精确表示，因为十进制的<code>0.1</code>换算成二进制是一个无限循环小数，很显然，无论使用<code>float</code>还是<code>double</code>，都只能存储一个<code>0.1</code>的近似值。但是，<code>0.5</code>这个浮点数又可以精确地表示。</p>
<p>因为浮点数常常无法精确表示，因此，浮点数运算会产生误差：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">double</span> x = <span class="number">1.0</span> / <span class="number">10</span>;</span><br><span class="line">        <span class="keyword">double</span> y = <span class="number">1</span> - <span class="number">9.0</span> / <span class="number">10</span>;</span><br><span class="line">        <span class="comment">// 观察x和y是否相等:</span></span><br><span class="line">        System.out.println(x);</span><br><span class="line">        System.out.println(y);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>由于浮点数存在运算误差，所以比较两个浮点数是否相等常常会出现错误的结果。正确的比较方法是判断两个浮点数之差的绝对值是否小于一个很小的数：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 比较x和y是否相等，先计算其差的绝对值:</span></span><br><span class="line"><span class="keyword">double</span> r = Math.abs(x - y);</span><br><span class="line"><span class="comment">// 再判断绝对值是否足够小:</span></span><br><span class="line"><span class="keyword">if</span> (r &lt; <span class="number">0.00001</span>) &#123;</span><br><span class="line">    <span class="comment">// 可以认为相等</span></span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="comment">// 不相等</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>浮点数在内存的表示方法和整数比更加复杂。Java的浮点数完全遵循IEEE-754标准，这也是绝大多数计算机平台都支持的浮点数标准表示方法。</p>
<h4 id="赋值与别名"><a href="#赋值与别名" class="headerlink" title="赋值与别名"></a>赋值与别名</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Assignment</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        ObjectAssignment();</span><br><span class="line">        System.out.println(<span class="string">"---------------------"</span>);</span><br><span class="line">        MethodAssignment();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title">ObjectAssignment</span><span class="params">()</span></span>&#123;</span><br><span class="line">        Number n1 = <span class="keyword">new</span> Number();</span><br><span class="line">        Number n2 = <span class="keyword">new</span> Number();</span><br><span class="line">        n1.i = <span class="number">9</span>;</span><br><span class="line">        n2.i = <span class="number">47</span>;</span><br><span class="line">        System.out.println(<span class="string">"n1.i = "</span> + n1.i+<span class="string">"\t"</span>+<span class="string">"n2.i = "</span> + n2.i);</span><br><span class="line">        <span class="comment">//n1.i = 9	n2.i = 47</span></span><br><span class="line">        n1 = n2;</span><br><span class="line">        System.out.println(<span class="string">"n1.i = "</span> + n1.i+<span class="string">"\t"</span>+<span class="string">"n2.i = "</span> + n2.i);</span><br><span class="line">        <span class="comment">//n1.i = 47	n2.i = 47</span></span><br><span class="line">        n1.i=<span class="number">27</span>;</span><br><span class="line">        System.out.println(<span class="string">"n1.i = "</span> + n1.i+<span class="string">"\t"</span>+<span class="string">"n2.i = "</span> + n2.i);</span><br><span class="line">        <span class="comment">//n1.i = 27	n2.i = 27</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title">MethodAssignment</span><span class="params">()</span></span>&#123;</span><br><span class="line">        Number n1 = <span class="keyword">new</span> Number();</span><br><span class="line">        Number n2 = <span class="keyword">new</span> Number();</span><br><span class="line">        n1.i = <span class="number">9</span>;</span><br><span class="line">        n2.i = <span class="number">47</span>;</span><br><span class="line">        System.out.println(<span class="string">"n1.i = "</span> + n1.i+<span class="string">"\t"</span>+<span class="string">"n2.i = "</span> + n2.i);</span><br><span class="line">        <span class="comment">//n1.i = 9	n2.i = 47</span></span><br><span class="line">        n1.i = n2.i;</span><br><span class="line">        System.out.println(<span class="string">"n1.i = "</span> + n1.i+<span class="string">"\t"</span>+<span class="string">"n2.i = "</span> + n2.i);</span><br><span class="line">        <span class="comment">//n1.i = 47	n2.i = 47</span></span><br><span class="line">        n1.i=<span class="number">27</span>;</span><br><span class="line">        System.out.println(<span class="string">"n1.i = "</span> + n1.i+<span class="string">"\t"</span>+<span class="string">"n2.i = "</span> + n2.i);</span><br><span class="line">        <span class="comment">//n1.i = 27	n2.i = 47</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Number</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> i;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>每个Number中的 i值都赋予了一个不同的值。随后，将 n2赋给 n1，而且 n1发生改变。在许多程序设计语言中，我们都希望n1和 n2任何时候都相互独立。看来改变n1的同时也改变了n2。这是由于无论n1还是 n2都包含了相同的句柄，它指向相同的对象（最初的句柄位于 n1内部，指向容纳了值9的一个对象。在赋值过程中，那个句柄实际已经丢失；它的对象会由“垃圾收集器”自动清除）。</p>
<p>这种特殊的现象通常也叫作“别名”，是 Java操作对象的一种基本方式。但假若不愿意在这种情况下出现别名，又该怎么操作呢？可放弃赋值，并写入下述代码： <code>n1.i = n2.i</code>这样便可保留两个独立的对象，而不是将 n1和 n2绑定到相同的对象。但您很快就会意识到，这样做会使对象内部的字段处理发生混乱，并与标准的面向对象设计准则相悖。</p>
<p><strong>类型提升</strong></p>
<p>如果参与运算的两个数其中一个是整型，那么整型可以自动提升到浮点型：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = <span class="number">5</span>;</span><br><span class="line">        <span class="keyword">double</span> d = <span class="number">1.2</span> + <span class="number">24.0</span> / n; <span class="comment">// 6.0</span></span><br><span class="line">        System.out.println(d);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>需要特别注意，在一个复杂的四则运算中，两个整数的运算不会出现自动提升的情况。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">double</span> d = <span class="number">1.2</span> + <span class="number">24</span> / <span class="number">5</span>; <span class="comment">// 5.2</span></span><br></pre></td></tr></table></figure>

<p>计算结果为<code>5.2</code>，原因是编译器计算<code>24 / 5</code>这个子表达式时，按两个整数进行运算，结果仍为整数<code>4</code>。</p>
<p> <strong>特殊值</strong></p>
<p>整数运算在除数为<code>0</code>时会报错，而浮点数运算在除数为<code>0</code>时，不会报错，但会返回几个特殊值：</p>
<ul>
<li><code>NaN</code>表示Not a Number</li>
<li><code>Infinity</code>表示无穷大</li>
<li><code>-Infinity</code>表示负无穷大</li>
</ul>
<p>例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">double</span> d1 = <span class="number">0.0</span> / <span class="number">0</span>; <span class="comment">// NaN</span></span><br><span class="line"><span class="keyword">double</span> d2 = <span class="number">1.0</span> / <span class="number">0</span>; <span class="comment">// Infinity</span></span><br><span class="line"><span class="keyword">double</span> d3 = -<span class="number">1.0</span> / <span class="number">0</span>; <span class="comment">// -Infinity</span></span><br></pre></td></tr></table></figure>

<p>这三种特殊值在实际运算中很少碰到，我们只需要了解即可。</p>
<p><strong>强制转型</strong></p>
<p>可以将浮点数强制转型为整数。在转型时，浮点数的小数部分会被丢掉。如果转型后超过了整型能表示的最大范围，将返回整型的最大值。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> n1 = (<span class="keyword">int</span>) <span class="number">12.3</span>; <span class="comment">// 12</span></span><br><span class="line"><span class="keyword">int</span> n2 = (<span class="keyword">int</span>) <span class="number">12.7</span>; <span class="comment">// 12</span></span><br><span class="line"><span class="keyword">int</span> n2 = (<span class="keyword">int</span>) -<span class="number">12.7</span>; <span class="comment">// -12</span></span><br><span class="line"><span class="keyword">int</span> n3 = (<span class="keyword">int</span>) (<span class="number">12.7</span> + <span class="number">0.5</span>); <span class="comment">// 13</span></span><br><span class="line"><span class="keyword">int</span> n4 = (<span class="keyword">int</span>) <span class="number">1.2e20</span>; <span class="comment">// 2147483647</span></span><br></pre></td></tr></table></figure>

<p>如果要进行四舍五入，可以对浮点数加上0.5再强制转型：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">double</span> d = <span class="number">2.6</span>;</span><br><span class="line">        <span class="keyword">int</span> n = (<span class="keyword">int</span>) (d + <span class="number">0.5</span>);</span><br><span class="line">        System.out.println(n);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="字符和字符串"><a href="#字符和字符串" class="headerlink" title="字符和字符串"></a>字符和字符串</h3><p>在Java中，字符和字符串是两个不同的类型。字符串是由一串字符（char 类型的值）组成的。</p>
<h4 id="字符的类型"><a href="#字符的类型" class="headerlink" title="字符的类型"></a>字符的类型</h4><p>字符类型<code>char</code>是基本数据类型，它是<code>character</code>的缩写。一个<code>char</code>保存一个Unicode字符：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">char</span> c1 = <span class="string">'A'</span>;</span><br><span class="line"><span class="keyword">char</span> c2 = <span class="string">'中'</span>;</span><br></pre></td></tr></table></figure>

<p>因为Java在内存中总是使用Unicode表示字符，所以，一个英文字符和一个中文字符都用一个<code>char</code>类型表示，它们都占用两个字节。要显示一个字符的Unicode编码，只需将<code>char</code>类型直接赋值给<code>int</code>类型即可：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> n1 = <span class="string">'A'</span>; <span class="comment">// 字母“A”的Unicodde编码是65</span></span><br><span class="line"><span class="keyword">int</span> n2 = <span class="string">'中'</span>; <span class="comment">// 汉字“中”的Unicode编码是20013</span></span><br></pre></td></tr></table></figure>

<p>还可以直接用转义字符<code>\u</code>+Unicode编码来表示一个字符：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 注意是十六进制:</span></span><br><span class="line"><span class="keyword">char</span> c3 = <span class="string">'\u0041'</span>; <span class="comment">// 'A'，因为十六进制0041 = 十进制65</span></span><br><span class="line"><span class="keyword">char</span> c4 = <span class="string">'\u4e2d'</span>; <span class="comment">// '中'，因为十六进制4e2d = 十进制20013</span></span><br></pre></td></tr></table></figure>

<h4 id="字符串类型"><a href="#字符串类型" class="headerlink" title="字符串类型"></a>字符串类型</h4><p>和<code>char</code>类型不同，字符串类型<code>String</code>是引用类型，我们用双引号<code>&quot;...&quot;</code>表示字符串。一个字符串可以存储0个到任意个字符：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">String s = <span class="string">""</span>; <span class="comment">// 空字符串，包含0个字符</span></span><br><span class="line">String s1 = <span class="string">"A"</span>; <span class="comment">// 包含一个字符</span></span><br><span class="line">String s2 = <span class="string">"ABC"</span>; <span class="comment">// 包含3个字符</span></span><br><span class="line">String s3 = <span class="string">"中文 ABC"</span>; <span class="comment">// 包含6个字符，其中有一个空格</span></span><br></pre></td></tr></table></figure>

<p>因为字符串使用双引号<code>&quot;...&quot;</code>表示开始和结束，那如果字符串本身恰好包含一个<code>&quot;</code>字符怎么表示？例如，<code>&quot;abc&quot;xyz&quot;</code>，编译器就无法判断中间的引号究竟是字符串的一部分还是表示字符串结束。这个时候，我们需要借助转义字符<code>\</code>：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">String s = <span class="string">"abc\"xyz"</span>; <span class="comment">// 包含7个字符: a, b, c, ", x, y, z</span></span><br></pre></td></tr></table></figure>

<p>因为<code>\</code>是转义字符，所以，两个<code>\\</code>表示一个<code>\</code>字符：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">String s = <span class="string">"abc\\xyz"</span>; <span class="comment">// 包含7个字符: a, b, c, \, x, y, z</span></span><br></pre></td></tr></table></figure>

<p>常见的转义字符包括：</p>
<ul>
<li><code>\&quot;</code> 表示字符<code>&quot;</code></li>
<li><code>\&#39;</code> 表示字符<code>&#39;</code></li>
<li><code>\\</code> 表示字符<code>\</code></li>
<li><code>\n</code> 表示换行符</li>
<li><code>\r</code> 表示回车符</li>
<li><code>\t</code> 表示Tab</li>
<li><code>\u####</code> 表示一个Unicode编码的字符</li>
</ul>
<p>例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">String s = <span class="string">"ABC\n\u4e2d\u6587"</span>; <span class="comment">// 包含6个字符: A, B, C, 换行符, 中, 文</span></span><br></pre></td></tr></table></figure>

<h4 id="字符串连接"><a href="#字符串连接" class="headerlink" title="字符串连接"></a>字符串连接</h4><p>Java的编译器对字符串做了特殊照顾，可以使用<code>+</code>连接任意字符串和其他数据类型，这样极大地方便了字符串的处理。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 字符串连接</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">    String s1 = <span class="string">"Hello"</span>;</span><br><span class="line">    String s2 = <span class="string">"world"</span>;</span><br><span class="line">    String s = s1 + <span class="string">" "</span> + s2 + <span class="string">"!"</span>;</span><br><span class="line">    System.out.println(s);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/*输出结果</span></span><br><span class="line"><span class="comment">Hello world!</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>

<p>如果用<code>+</code>连接字符串和其他数据类型，会将其他数据类型先自动转型为字符串，再连接：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 字符串连接</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> age = <span class="number">25</span>;</span><br><span class="line">    String s = <span class="string">"age is "</span> + age;</span><br><span class="line">    System.out.println(s);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/*输出结果</span></span><br><span class="line"><span class="comment">age is 25</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>

<h4 id="多行字符串"><a href="#多行字符串" class="headerlink" title="多行字符串"></a>多行字符串</h4><p>如果我们要表示多行字符串，使用+号连接会非常不方便：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">String s = <span class="string">"first line \n"</span></span><br><span class="line">         + <span class="string">"second line \n"</span></span><br><span class="line">         + <span class="string">"end"</span>;</span><br></pre></td></tr></table></figure>

<p>从Java 13开始，字符串可以用<code>&quot;&quot;&quot;...&quot;&quot;&quot;</code>表示多行字符串（Text Blocks）了。举个例子：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 多行字符串</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        String s = <span class="string">""</span><span class="string">"</span></span><br><span class="line"><span class="string">                   SELECT * FROM</span></span><br><span class="line"><span class="string">                     users</span></span><br><span class="line"><span class="string">                   WHERE id &gt; 100</span></span><br><span class="line"><span class="string">                   ORDER BY name DESC</span></span><br><span class="line"><span class="string">                   "</span><span class="string">""</span>;</span><br><span class="line">        System.out.println(s);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>上述多行字符串实际上是5行，在最后一个<code>DESC</code>后面还有一个<code>\n</code>。如果我们不想在字符串末尾加一个<code>\n</code>，就需要这么写：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">String s = <span class="string">""</span><span class="string">"</span></span><br><span class="line"><span class="string">           SELECT * FROM</span></span><br><span class="line"><span class="string">             users</span></span><br><span class="line"><span class="string">           WHERE id &gt; 100</span></span><br><span class="line"><span class="string">           ORDER BY name DESC"</span><span class="string">""</span>;</span><br></pre></td></tr></table></figure>

<p>还需要注意到，多行字符串前面共同的空格会被去掉，即：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">String s = <span class="string">""</span><span class="string">"</span></span><br><span class="line"><span class="string">...........SELECT * FROM</span></span><br><span class="line"><span class="string">...........  users</span></span><br><span class="line"><span class="string">...........WHERE id &gt; 100</span></span><br><span class="line"><span class="string">...........ORDER BY name DESC</span></span><br><span class="line"><span class="string">..........."</span><span class="string">""</span>;</span><br></pre></td></tr></table></figure>

<p>用<code>.</code>标注的空格都会被去掉。</p>
<p>如果多行字符串的排版不规则，那么，去掉的空格就会变成这样：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">String s = <span class="string">""</span><span class="string">"</span></span><br><span class="line"><span class="string">.........  SELECT * FROM</span></span><br><span class="line"><span class="string">.........    users</span></span><br><span class="line"><span class="string">.........WHERE id &gt; 100</span></span><br><span class="line"><span class="string">.........  ORDER BY name DESC</span></span><br><span class="line"><span class="string">.........  "</span><span class="string">""</span>;</span><br></pre></td></tr></table></figure>

<p>即总是以最短的行首空格为基准。</p>
<p>最后，由于多行字符串是作为Java 13的预览特性（Preview Language Features）实现的，编译的时候，我们还需要给编译器加上参数：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">javac --source <span class="number">13</span> --enable-preview Main.java</span><br></pre></td></tr></table></figure>

<h4 id="不可变特性"><a href="#不可变特性" class="headerlink" title="不可变特性"></a>不可变特性</h4><p>Java的字符串除了是一个引用类型外，还有个重要特点，就是字符串不可变。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 字符串不可变</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        String s = <span class="string">"hello"</span>;</span><br><span class="line">        System.out.println(s); <span class="comment">// 输出 hello</span></span><br><span class="line">        s = <span class="string">"world"</span>;</span><br><span class="line">        System.out.println(s); <span class="comment">// 输出 world</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>观察执行结果，难道字符串<code>s</code>变了吗？其实变的不是字符串，而是变量<code>s</code>的“指向”。</p>
<p>执行<code>String s = &quot;hello&quot;;</code>时，JVM虚拟机先创建字符串<code>&quot;hello&quot;</code>，然后，把字符串变量<code>s</code>指向它：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">      s</span><br><span class="line">      │</span><br><span class="line">      ▼</span><br><span class="line">┌───┬───────────┬───┐</span><br><span class="line">│   │  &quot;hello&quot;  │   │</span><br><span class="line">└───┴───────────┴───┘</span><br></pre></td></tr></table></figure>

<p>紧接着，执行<code>s = &quot;world&quot;;</code>时，JVM虚拟机先创建字符串<code>&quot;world&quot;</code>，然后，把字符串变量<code>s</code>指向它：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">      s ──────────────┐</span><br><span class="line">                      │</span><br><span class="line">                      ▼</span><br><span class="line">┌───┬───────────┬───┬───────────┬───┐</span><br><span class="line">│   │  &quot;hello&quot;  │   │  &quot;world&quot;  │   │</span><br><span class="line">└───┴───────────┴───┴───────────┴───┘</span><br></pre></td></tr></table></figure>

<p>原来的字符串<code>&quot;hello&quot;</code>还在，只是我们无法通过变量<code>s</code>访问它而已。因此，字符串的不可变是指字符串内容不可变。</p>
<p>理解了引用类型的“指向”后，试解释下面的代码输出：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 字符串不可变</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        String s = <span class="string">"hello"</span>;</span><br><span class="line">        String t = s;</span><br><span class="line">        s = <span class="string">"world"</span>;</span><br><span class="line">        System.out.println(t); <span class="comment">// t是"hello"还是"world"?</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="空值null"><a href="#空值null" class="headerlink" title="空值null"></a>空值null</h4><p>引用类型的变量可以指向一个空值<code>null</code>，它表示不存在，即该变量不指向任何对象。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">String s1 = <span class="keyword">null</span>; <span class="comment">// s1是null</span></span><br><span class="line">String s2; <span class="comment">// 没有赋初值值，s2也是null</span></span><br><span class="line">String s3 = s1; <span class="comment">// s3也是null</span></span><br><span class="line">String s4 = <span class="string">""</span>; <span class="comment">// s4指向空字符串，不是null</span></span><br></pre></td></tr></table></figure>

<p>注意要区分空值<code>null</code>和空字符串<code>&quot;&quot;</code>，空字符串是一个有效的字符串对象，它不等于<code>null</code>。</p>
<h4 id="类型转换"><a href="#类型转换" class="headerlink" title="类型转换"></a>类型转换</h4><p>字符串的两个主要用途分别是将用户从键盘输入的内容转换成相应数据类型的值以及将各种数据类型的值转化成能够在屏幕上显示的内容。Java 的 String 类型为这些操作内置了相应的方法，而且 Integer 和 Double 库还包含了分别和 String 类型相互转化的静态方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">    String strings = <span class="string">"123"</span>;</span><br><span class="line">    <span class="keyword">int</span> number = <span class="number">123</span>;</span><br><span class="line">    System.out.println(<span class="string">"Integer.parseInt(strings) = "</span> + Integer.parseInt(strings));</span><br><span class="line">    System.out.println(<span class="string">"Integer.toString(number) = "</span> + Integer.toString(number));</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//将字符串strings转换为整数</span></span><br><span class="line"><span class="comment">//Integer.parseInt(strings) = 123</span></span><br><span class="line"><span class="comment">//将整数number转换为字符串</span></span><br><span class="line"><span class="comment">//Integer.toString(number) = 123</span></span><br></pre></td></tr></table></figure>

<h2 id="语句"><a href="#语句" class="headerlink" title="语句"></a>语句</h2><p>语句是 Java 语言中可执行代码的基本单位，表达程序员的某个意图。和表达式不同，Java语句没有返回值。语句一般包含表达式和运算符（尤其是赋值运算符），执行的目的往往是为了它们的副作用。</p>
<p>Java 定义的很多语句是流程控制语句，例如条件语句和循环语句，它们通过合理的方式改变默认的线性执行顺序。</p>
<table>
<thead>
<tr>
<th>语 句</th>
<th>作  用</th>
<th>句  法</th>
</tr>
</thead>
<tbody><tr>
<td>表达式</td>
<td>副作用</td>
<td><code>var = expr; expr++; method(); new Type();</code></td>
</tr>
<tr>
<td>复合语句</td>
<td>语句组</td>
<td><code>{ statements }</code></td>
</tr>
<tr>
<td>空语句</td>
<td>无作用</td>
<td><code>;</code></td>
</tr>
<tr>
<td>标注</td>
<td>为语句命名</td>
<td><code>label: statement</code></td>
</tr>
<tr>
<td>变量</td>
<td>声明变量</td>
<td><code>[final] type name[=value][,name[=value]] ...;</code></td>
</tr>
<tr>
<td>if</td>
<td>条件判断</td>
<td><code>if (expr) statement[ else statement]</code></td>
</tr>
<tr>
<td>switch</td>
<td>条件判断</td>
<td><code>switch (expr) { [ case expr : statements ] ... [ default: statements ] }</code></td>
</tr>
<tr>
<td>while</td>
<td>循环</td>
<td><code>while (expr) statement</code></td>
</tr>
<tr>
<td>do</td>
<td>循环</td>
<td><code>do statement while (expr);</code></td>
</tr>
<tr>
<td>for</td>
<td>简单循环</td>
<td><code>for (init; test; increment) statement</code></td>
</tr>
<tr>
<td>遍历</td>
<td>迭代集合</td>
<td><code>for (variable : iterable) statement</code></td>
</tr>
<tr>
<td>break</td>
<td>退出块</td>
<td><code>break [label];</code></td>
</tr>
<tr>
<td>continue</td>
<td>重新开始循环</td>
<td><code>continue [label];</code></td>
</tr>
<tr>
<td>return</td>
<td>结束方法</td>
<td><code>return [expr];</code></td>
</tr>
<tr>
<td>synchronized</td>
<td>临界区</td>
<td><code>synchronized (expr) {statements}</code></td>
</tr>
<tr>
<td>throw</td>
<td>抛出异常</td>
<td><code>throw expr;</code></td>
</tr>
<tr>
<td>try</td>
<td>处理异常</td>
<td><code>try {statements}[ catch (type name) { statements } ] ... [ finally { statements } ]</code></td>
</tr>
<tr>
<td>assert</td>
<td>验证不变式</td>
<td><code>assert invariant[ :error];</code></td>
</tr>
</tbody></table>
<h3 id="表达式语句"><a href="#表达式语句" class="headerlink" title="表达式语句"></a>表达式语句</h3><p>本章前面已经说过，某些 Java 表达式有副作用。也就是说，这些表达式不仅能计算得到的一个值，还能以某种方式改变程序的状态。只要表达式有副作用，在表达式后面加上分号就能作为语句使用。合法的表达式语句有赋值、递增和递减、方法调用以及对象创建。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">a = <span class="number">1</span>;                              <span class="comment">// 赋值 </span></span><br><span class="line">x *= <span class="number">2</span>;                             <span class="comment">// 带运算的赋值 </span></span><br><span class="line">i++;                                <span class="comment">// 后递增 </span></span><br><span class="line">--c;                                <span class="comment">// 前递减 </span></span><br><span class="line">System.out.println(<span class="string">"statement"</span>);    <span class="comment">// 方法调用</span></span><br></pre></td></tr></table></figure>

<h3 id="复合语句"><a href="#复合语句" class="headerlink" title="复合语句"></a>复合语句</h3><p>复合语句是一些放在花括号里的语句，语句的数量和类型不限。Java 句法规定可以使用语句的地方都可以使用复合语句：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">10</span>; i++) &#123; </span><br><span class="line">   a[i]++;           <span class="comment">// 这个循环体是一个复合语句 </span></span><br><span class="line">   b[i]--;           <span class="comment">// 包括两个表达式语句 </span></span><br><span class="line">&#125;                    <span class="comment">// 放在花括号里</span></span><br></pre></td></tr></table></figure>

<h3 id="空语句"><a href="#空语句" class="headerlink" title="空语句"></a>空语句</h3><p>在 Java 中，空语句使用一个分号表示。空语句什么也不做，不过这种句法偶尔有用。例如，在 for 循环中可以使用空语句表明循环体为空：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">10</span>; a[i++]++)  <span class="comment">// 递增数组元素 </span></span><br><span class="line">     <span class="comment">/* empty */</span>;                 <span class="comment">// 循环体是空语句</span></span><br></pre></td></tr></table></figure>

<h3 id="标注语句"><a href="#标注语句" class="headerlink" title="标注语句"></a>标注语句</h3><p>标注语句就是有名称的语句。命名方法是，在语句前加上一个标识符和一个冒号。<code>break</code>和 <code>continue</code> 语句会用到标注。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">rowLoop: <span class="keyword">for</span>(<span class="keyword">int</span> r = <span class="number">0</span>; r &lt; rows.length; r++) &#123;        <span class="comment">// 一个标注循环 </span></span><br><span class="line">   colLoop: <span class="keyword">for</span>(<span class="keyword">int</span> c = <span class="number">0</span>; c &lt; columns.length; c++) &#123;  <span class="comment">// 另一个 </span></span><br><span class="line">     <span class="keyword">break</span> rowLoop;                                    <span class="comment">// 使用标注 </span></span><br><span class="line">   &#125; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="局部变量声明语句"><a href="#局部变量声明语句" class="headerlink" title="局部变量声明语句"></a>局部变量声明语句</h3><p>局部变量经常直接称为变量，是值存储位置的符号名称，在方法和复合语句中定义。所有变量在使用之前必须先声明，声明变量的方法是使用声明语句。Java 是静态类型语言，声明变量时要指定变量的类型，而且只有这种类型的值才能存储在这个变量中。变量声明语句最简单的形式只需指定变量的类型和名称：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> counter; </span><br><span class="line">String s;</span><br></pre></td></tr></table></figure>

<p>声明变量时还可以包含一个初始化表达式，用于指定变量的初始值。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> i = <span class="number">0</span>; </span><br><span class="line">String s = readLine(); </span><br><span class="line"><span class="keyword">int</span>[] data = &#123;x+<span class="number">1</span>, x+<span class="number">2</span>, x+<span class="number">3</span>&#125;; <span class="comment">// 稍后会介绍数组初始化表达式</span></span><br></pre></td></tr></table></figure>

<p>Java 编译器不允许使用未初始化的局部变量，所以，方便起见，通常会在一个语句中同时声明和初始化变量。初始化表达式不必是编译器能计算得到结果的字面量或常量表达式，也可以是程序运行时能计算出结果的任意复杂表达式。一个变量声明语句可以声明和初始化多个变量，但是所有变量必须是同一类型。变量名称和可选的初始化表达式使用逗号分隔：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> i, j, k;   </span><br><span class="line"><span class="keyword">float</span> x = <span class="number">1.0</span>, y = <span class="number">1.0</span>; </span><br><span class="line">String question = <span class="string">"Really Quit?"</span>, response;</span><br></pre></td></tr></table></figure>


<p>变量声明语句可以以 <code>final</code> 关键字开头。这个修饰符表明，为变量指定初始值之后，其值就不能改变了：</p>
<p>在 Java 代码的任何地方都能使用变量声明语句，而不局限于只能在方法和代码块的开头使用。局部变量声明还可以集成到 for 循环的初始化部分里。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">method</span><span class="params">()</span> </span>&#123;           <span class="comment">// 定义一个方法 </span></span><br><span class="line">   <span class="keyword">int</span> i = <span class="number">0</span>;             <span class="comment">// 声明变量i </span></span><br><span class="line">   <span class="keyword">while</span> (i &lt; <span class="number">10</span>) &#123;       <span class="comment">// 在这个作用域里可以使用i </span></span><br><span class="line">     <span class="keyword">int</span> j = <span class="number">0</span>;           <span class="comment">// 声明变量j；j的作用域从这里开始 </span></span><br><span class="line">     i++;                 <span class="comment">// 在这个作用域里可以使用i；递增i </span></span><br><span class="line">   &#125;                      <span class="comment">// 在这个作用域里不能使用j了 </span></span><br><span class="line">   System.out.println(i); <span class="comment">// 在这个作用域里仍能使用i </span></span><br><span class="line">&#125;                         <span class="comment">// i的作用域在这结束</span></span><br></pre></td></tr></table></figure>

<h3 id="if-else语句"><a href="#if-else语句" class="headerlink" title="if/else语句"></a><code>if</code>/<code>else</code>语句</h3><p>if 语句是基本的控制语句，允许 Java 作出判断，或者更准确地说，根据条件决定执行哪些语句。</p>
<ul>
<li>如果表达式的计算结果为 true，解释器会执行关联的语句；</li>
<li>如果表达式的计算结果为 false，解释器会跳过关联的语句。</li>
</ul>
<p><code>if</code>语句的基本语法是：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (条件) &#123;</span><br><span class="line">    <span class="comment">// 条件满足时执行</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>根据<code>if</code>的计算结果（<code>true</code>还是<code>false</code>），JVM决定是否执行<code>if</code>语句块（即花括号{}包含的所有语句）。</p>
<p>让我们来看一个例子：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 条件判断</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = <span class="number">70</span>;</span><br><span class="line">        <span class="keyword">if</span> (n &gt;= <span class="number">60</span>) &#123;</span><br><span class="line">            System.out.println(<span class="string">"及格了"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(<span class="string">"END"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>当条件<code>n &gt;= 60</code>计算结果为<code>true</code>时，<code>if</code>语句块被执行，将打印<code>&quot;及格了&quot;</code>，否则，<code>if</code>语句块将被跳过。修改<code>n</code>的值可以看到执行效果。</p>
<p>注意到<code>if</code>语句包含的块可以包含多条语句：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 条件判断</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = <span class="number">70</span>;</span><br><span class="line">        <span class="keyword">if</span> (n &gt;= <span class="number">60</span>) &#123;</span><br><span class="line">            System.out.println(<span class="string">"及格了"</span>);</span><br><span class="line">            System.out.println(<span class="string">"恭喜你"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(<span class="string">"END"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>当<code>if</code>语句块只有一行语句时，可以省略花括号{}：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 条件判断</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = <span class="number">70</span>;</span><br><span class="line">        <span class="keyword">if</span> (n &gt;= <span class="number">60</span>)</span><br><span class="line">            System.out.println(<span class="string">"及格了"</span>);</span><br><span class="line">        System.out.println(<span class="string">"END"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>但是，省略花括号并不总是一个好主意。假设某个时候，突然想给<code>if</code>语句块增加一条语句时：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 条件判断</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = <span class="number">50</span>;</span><br><span class="line">        <span class="keyword">if</span> (n &gt;= <span class="number">60</span>)</span><br><span class="line">            System.out.println(<span class="string">"及格了"</span>);</span><br><span class="line">            System.out.println(<span class="string">"恭喜你"</span>); <span class="comment">// 注意这条语句不是if语句块的一部分</span></span><br><span class="line">        System.out.println(<span class="string">"END"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p> 由于使用缩进格式，很容易把两行语句都看成<code>if</code>语句的执行块，但实际上只有第一行语句是<code>if</code>的执行块。在使用git这些版本控制系统自动合并时更容易出问题，所以不推荐忽略花括号的写法。</p>
<hr>
<p><code>if</code>语句还可以编写一个<code>else { ... }</code>，当条件判断为<code>false</code>时，将执行<code>else</code>的语句块：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 条件判断</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = <span class="number">70</span>;</span><br><span class="line">        <span class="keyword">if</span> (n &gt;= <span class="number">60</span>) &#123;</span><br><span class="line">            System.out.println(<span class="string">"及格了"</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">"挂科了"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(<span class="string">"END"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>修改上述代码<code>n</code>的值，观察<code>if</code>条件为<code>true</code>或<code>false</code>时，程序执行的语句块。</p>
<p>注意，<code>else</code>不是必须的。</p>
<p>还可以用多个<code>if ... else if ...</code>串联。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 条件判断</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = <span class="number">70</span>;</span><br><span class="line">        <span class="keyword">if</span> (n &gt;= <span class="number">90</span>) &#123;</span><br><span class="line">            System.out.println(<span class="string">"优秀"</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (n &gt;= <span class="number">60</span>) &#123;</span><br><span class="line">            System.out.println(<span class="string">"及格了"</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">"挂科了"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(<span class="string">"END"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>串联的效果其实相当于：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (n &gt;= <span class="number">90</span>) &#123;</span><br><span class="line">    <span class="comment">// n &gt;= 90为true:</span></span><br><span class="line">    System.out.println(<span class="string">"优秀"</span>);</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="comment">// n &gt;= 90为false:</span></span><br><span class="line">    <span class="keyword">if</span> (n &gt;= <span class="number">60</span>) &#123;</span><br><span class="line">        <span class="comment">// n &gt;= 60为true:</span></span><br><span class="line">        System.out.println(<span class="string">"及格了"</span>);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="comment">// n &gt;= 60为false:</span></span><br><span class="line">        System.out.println(<span class="string">"挂科了"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在串联使用多个<code>if</code>时，要<em>特别注意</em>判断顺序。观察下面的代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 条件判断</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = <span class="number">100</span>;</span><br><span class="line">        <span class="keyword">if</span> (n &gt;= <span class="number">60</span>) &#123;</span><br><span class="line">            System.out.println(<span class="string">"及格了"</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (n &gt;= <span class="number">90</span>) &#123;</span><br><span class="line">            System.out.println(<span class="string">"优秀"</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">"挂科了"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>执行发现，<code>n = 100</code>时，满足条件<code>n &gt;= 90</code>，但输出的不是<code>&quot;优秀&quot;</code>，而是<code>&quot;及格了&quot;</code>，原因是<code>if</code>语句从上到下执行时，先判断<code>n &gt;= 60</code>成功后，后续<code>else</code>不再执行，因此，<code>if (n &gt;= 90)</code>没有机会执行了。</p>
<p>正确的方式是按照判断范围从大到小依次判断：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 从大到小依次判断：</span></span><br><span class="line"><span class="keyword">if</span> (n &gt;= <span class="number">90</span>) &#123;</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125; <span class="keyword">else</span> <span class="keyword">if</span> (n &gt;= <span class="number">60</span>) &#123;</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>或者改写成从小到大依次判断：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 从小到大依次判断：</span></span><br><span class="line"><span class="keyword">if</span> (n &lt; <span class="number">60</span>) &#123;</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125; <span class="keyword">else</span> <span class="keyword">if</span> (n &lt; <span class="number">90</span>) &#123;</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>使用<code>if</code>时，还要特别注意边界条件。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 条件判断</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n = <span class="number">90</span>;</span><br><span class="line">        <span class="keyword">if</span> (n &gt; <span class="number">90</span>) &#123;</span><br><span class="line">            System.out.println(<span class="string">"优秀"</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (n &gt;= <span class="number">60</span>) &#123;</span><br><span class="line">            System.out.println(<span class="string">"及格了"</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">"挂科了"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>假设我们期望90分或更高为“优秀”，上述代码输出的却是“及格”，原因是<code>&gt;</code>和<code>&gt;=</code>效果是不同的。</p>
<p>前面讲过了浮点数在计算机中常常无法精确表示，并且计算可能出现误差，因此，判断浮点数相等用<code>==</code>判断不靠谱：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 条件判断</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">double</span> x = <span class="number">1</span> - <span class="number">9.0</span> / <span class="number">10</span>;</span><br><span class="line">        <span class="keyword">if</span> (x == <span class="number">0.1</span>) &#123;</span><br><span class="line">            System.out.println(<span class="string">"x is 0.1"</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">"x is NOT 0.1"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>正确的方法是利用差值小于某个临界值来判断：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 条件判断</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">double</span> x = <span class="number">1</span> - <span class="number">9.0</span> / <span class="number">10</span>;</span><br><span class="line">        <span class="keyword">if</span> (Math.abs(x - <span class="number">0.1</span>) &lt; <span class="number">0.00001</span>) &#123;</span><br><span class="line">            System.out.println(<span class="string">"x is 0.1"</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">"x is NOT 0.1"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>判断引用类型相等</p>
<p>在Java中，判断值类型的变量是否相等，可以使用<code>==</code>运算符。但是，判断引用类型的变量是否相等，<code>==</code>表示“引用是否相等”，或者说，是否指向同一个对象。例如，下面的两个String类型，它们的内容是相同的，但是，分别指向不同的对象，用<code>==</code>判断，结果为<code>false</code>：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 条件判断</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        String s1 = <span class="string">"hello"</span>;</span><br><span class="line">        String s2 = <span class="string">"HELLO"</span>.toLowerCase();</span><br><span class="line">        System.out.println(s1);</span><br><span class="line">        System.out.println(s2);</span><br><span class="line">        <span class="keyword">if</span> (s1 == s2) &#123;</span><br><span class="line">            System.out.println(<span class="string">"s1 == s2"</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">"s1 != s2"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>要判断引用类型的变量内容是否相等，必须使用<code>equals()</code>方法：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 条件判断</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        String s1 = <span class="string">"hello"</span>;</span><br><span class="line">        String s2 = <span class="string">"HELLO"</span>.toLowerCase();</span><br><span class="line">        System.out.println(s1);</span><br><span class="line">        System.out.println(s2);</span><br><span class="line">        <span class="keyword">if</span> (s1.equals(s2)) &#123;</span><br><span class="line">            System.out.println(<span class="string">"s1 equals s2"</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">"s1 not equals s2"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>注意：执行语句<code>s1.equals(s2)</code>时，如果变量<code>s1</code>为<code>null</code>，会报<code>NullPointerException</code>：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 条件判断</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        String s1 = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">if</span> (s1.equals(<span class="string">"hello"</span>)) &#123;</span><br><span class="line">            System.out.println(<span class="string">"hello"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>要避免<code>NullPointerException</code>错误，可以利用短路运算符<code>&amp;&amp;</code>：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 条件判断</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        String s1 = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">if</span> (s1 != <span class="keyword">null</span> &amp;&amp; s1.equals(<span class="string">"hello"</span>)) &#123;</span><br><span class="line">            System.out.println(<span class="string">"hello"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p> 还可以把一定不是<code>null</code>的对象<code>&quot;hello&quot;</code>放到前面：例如：<code>if (&quot;hello&quot;.equals(s)) { ... }</code>。</p>
<h3 id="switch多重选择"><a href="#switch多重选择" class="headerlink" title="switch多重选择"></a><code>switch</code>多重选择</h3><p>除了if语句外，还有一种条件判断，是根据某个表达式的结果，分别去执行不同的分支。</p>
<p>例如，在游戏中，让用户选择选项：</p>
<ol>
<li>单人模式</li>
<li>多人模式</li>
<li>退出游戏</li>
</ol>
<p>这时，<code>switch</code>语句就派上用场了。</p>
<p><code>switch</code>语句根据<code>switch (表达式)</code>计算的结果，跳转到匹配的<code>case</code>结果，然后继续执行后续语句，直到遇到<code>break</code>结束执行。</p>
<p>我们看一个例子：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// switch</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> option = <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">switch</span> (option) &#123;</span><br><span class="line">        <span class="keyword">case</span> <span class="number">1</span>:</span><br><span class="line">            System.out.println(<span class="string">"Selected 1"</span>);</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">case</span> <span class="number">2</span>:</span><br><span class="line">            System.out.println(<span class="string">"Selected 2"</span>);</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">case</span> <span class="number">3</span>:</span><br><span class="line">            System.out.println(<span class="string">"Selected 3"</span>);</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>修改<code>option</code>的值分别为<code>1</code>、<code>2</code>、<code>3</code>，观察执行结果。</p>
<p>如果<code>option</code>的值没有匹配到任何<code>case</code>，例如<code>option = 99</code>，那么，<code>switch</code>语句不会执行任何语句。这时，可以给<code>switch</code>语句加一个<code>default</code>，当没有匹配到任何<code>case</code>时，执行<code>default</code>：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// switch</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> option = <span class="number">99</span>;</span><br><span class="line">        <span class="keyword">switch</span> (option) &#123;</span><br><span class="line">        <span class="keyword">case</span> <span class="number">1</span>:</span><br><span class="line">            System.out.println(<span class="string">"Selected 1"</span>);</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">case</span> <span class="number">2</span>:</span><br><span class="line">            System.out.println(<span class="string">"Selected 2"</span>);</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">case</span> <span class="number">3</span>:</span><br><span class="line">            System.out.println(<span class="string">"Selected 3"</span>);</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">default</span>:</span><br><span class="line">            System.out.println(<span class="string">"Not selected"</span>);</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>如果把<code>switch</code>语句翻译成<code>if</code>语句，那么上述的代码相当于：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (option == <span class="number">1</span>) &#123;</span><br><span class="line">    System.out.println(<span class="string">"Selected 1"</span>);</span><br><span class="line">&#125; <span class="keyword">else</span> <span class="keyword">if</span> (option == <span class="number">2</span>) &#123;</span><br><span class="line">    System.out.println(<span class="string">"Selected 2"</span>);</span><br><span class="line">&#125; <span class="keyword">else</span> <span class="keyword">if</span> (option == <span class="number">3</span>) &#123;</span><br><span class="line">    System.out.println(<span class="string">"Selected 3"</span>);</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    System.out.println(<span class="string">"Not selected"</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>对于多个<code>==</code>判断的情况，使用<code>switch</code>结构更加清晰。</p>
<p>同时注意，上述“翻译”只有在<code>switch</code>语句中对每个<code>case</code>正确编写了<code>break</code>语句才能对应得上。</p>
<p>使用<code>switch</code>时，注意<code>case</code>语句并没有花括号<code>{}</code>，而且，<code>case</code>语句具有“<strong>穿透性</strong>”，漏写<code>break</code>将导致意想不到的结果：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// switch</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> option = <span class="number">2</span>;</span><br><span class="line">        <span class="keyword">switch</span> (option) &#123;</span><br><span class="line">        <span class="keyword">case</span> <span class="number">1</span>:</span><br><span class="line">            System.out.println(<span class="string">"Selected 1"</span>);</span><br><span class="line">        <span class="keyword">case</span> <span class="number">2</span>:</span><br><span class="line">            System.out.println(<span class="string">"Selected 2"</span>);</span><br><span class="line">        <span class="keyword">case</span> <span class="number">3</span>:</span><br><span class="line">            System.out.println(<span class="string">"Selected 3"</span>);</span><br><span class="line">        <span class="keyword">default</span>:</span><br><span class="line">            System.out.println(<span class="string">"Not selected"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>当<code>option = 2</code>时，将依次输出<code>&quot;Selected 2&quot;</code>、<code>&quot;Selected 3&quot;</code>、<code>&quot;Not selected&quot;</code>，原因是从匹配到<code>case 2</code>开始，后续语句将全部执行，直到遇到<code>break</code>语句。因此，任何时候都不要忘记写<code>break</code>。</p>
<p>如果有几个<code>case</code>语句执行的是同一组语句块，可以这么写：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// switch</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> option = <span class="number">2</span>;</span><br><span class="line">        <span class="keyword">switch</span> (option) &#123;</span><br><span class="line">        <span class="keyword">case</span> <span class="number">1</span>:</span><br><span class="line">            System.out.println(<span class="string">"Selected 1"</span>);</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">case</span> <span class="number">2</span>:</span><br><span class="line">        <span class="keyword">case</span> <span class="number">3</span>:</span><br><span class="line">            System.out.println(<span class="string">"Selected 2, 3"</span>);</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">default</span>:</span><br><span class="line">            System.out.println(<span class="string">"Not selected"</span>);</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>使用<code>switch</code>语句时，只要保证有<code>break</code>，<code>case</code>的顺序不影响程序逻辑：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">switch</span> (option) &#123;</span><br><span class="line"><span class="keyword">case</span> <span class="number">3</span>:</span><br><span class="line">    ...</span><br><span class="line">    <span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> <span class="number">2</span>:</span><br><span class="line">    ...</span><br><span class="line">    <span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> <span class="number">1</span>:</span><br><span class="line">    ...</span><br><span class="line">    <span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>但是仍然建议按照自然顺序排列，便于阅读。</p>
<p><code>switch</code>语句还可以匹配字符串。字符串匹配时，是比较“内容相等”。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// switch</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        String fruit = <span class="string">"apple"</span>;</span><br><span class="line">        <span class="keyword">switch</span> (fruit) &#123;</span><br><span class="line">        <span class="keyword">case</span> <span class="string">"apple"</span>:</span><br><span class="line">            System.out.println(<span class="string">"Selected apple"</span>);</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">case</span> <span class="string">"pear"</span>:</span><br><span class="line">            System.out.println(<span class="string">"Selected pear"</span>);</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">case</span> <span class="string">"mango"</span>:</span><br><span class="line">            System.out.println(<span class="string">"Selected mango"</span>);</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">default</span>:</span><br><span class="line">            System.out.println(<span class="string">"No fruit selected"</span>);</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><code>switch</code>语句还可以使用枚举类型，枚举类型我们在后面讲解。</p>
<h4 id="switch表达式"><a href="#switch表达式" class="headerlink" title="switch表达式"></a><code>switch</code>表达式</h4><p>使用<code>switch</code>时，如果遗漏了<code>break</code>，就会造成严重的逻辑错误，而且不易在源代码中发现错误。从Java 12开始，<code>switch</code>语句升级为更简洁的表达式语法，使用类似模式匹配（Pattern Matching）的方法，保证只有一种路径会被执行，并且不需要<code>break</code>语句：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// switch</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        String fruit = <span class="string">"apple"</span>;</span><br><span class="line">        <span class="keyword">switch</span> (fruit) &#123;</span><br><span class="line">        <span class="keyword">case</span> <span class="string">"apple"</span> -&gt; System.out.println(<span class="string">"Selected apple"</span>);</span><br><span class="line">        <span class="keyword">case</span> <span class="string">"pear"</span> -&gt; System.out.println(<span class="string">"Selected pear"</span>);</span><br><span class="line">        <span class="keyword">case</span> <span class="string">"mango"</span> -&gt; &#123;</span><br><span class="line">            System.out.println(<span class="string">"Selected mango"</span>);</span><br><span class="line">            System.out.println(<span class="string">"Good choice!"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">default</span> -&gt; System.out.println(<span class="string">"No fruit selected"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>注意新语法使用<code>-&gt;</code>，如果有多条语句，需要用<code>{}</code>括起来。不要写<code>break</code>语句，因为新语法只会执行匹配的语句，没有穿透效应。</p>
<p>很多时候，我们还可能用<code>switch</code>语句给某个变量赋值。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> opt;</span><br><span class="line"><span class="keyword">switch</span> (fruit) &#123;</span><br><span class="line"><span class="keyword">case</span> <span class="string">"apple"</span>:</span><br><span class="line">    opt = <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> <span class="string">"pear"</span>:</span><br><span class="line"><span class="keyword">case</span> <span class="string">"mango"</span>:</span><br><span class="line">    opt = <span class="number">2</span>;</span><br><span class="line">    <span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">default</span>:</span><br><span class="line">    opt = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>使用新的<code>switch</code>语法，不但不需要<code>break</code>，还可以直接返回值。把上面的代码改写如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// switch</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        String fruit = <span class="string">"apple"</span>;</span><br><span class="line">        <span class="keyword">int</span> opt = <span class="keyword">switch</span> (fruit) &#123;</span><br><span class="line">            <span class="keyword">case</span> <span class="string">"apple"</span> -&gt; <span class="number">1</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="string">"pear"</span>, <span class="string">"mango"</span> -&gt; <span class="number">2</span>;</span><br><span class="line">            <span class="keyword">default</span> -&gt; <span class="number">0</span>;</span><br><span class="line">        &#125;; <span class="comment">// 注意赋值语句要以;结束</span></span><br><span class="line">        System.out.println(<span class="string">"opt = "</span> + opt);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这样可以获得更简洁的代码。</p>
<h4 id="yield"><a href="#yield" class="headerlink" title="yield"></a><code>yield</code></h4><p>大多数时候，在<code>switch</code>表达式内部，我们会返回简单的值。</p>
<p>但是，如果需要复杂的语句，我们也可以写很多语句，放到<code>{...}</code>里，然后，用<code>yield</code>返回一个值作为<code>switch</code>语句的返回值：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// yield</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        String fruit = <span class="string">"orange"</span>;</span><br><span class="line">        <span class="keyword">int</span> opt = <span class="keyword">switch</span> (fruit) &#123;</span><br><span class="line">            <span class="keyword">case</span> <span class="string">"apple"</span> -&gt; <span class="number">1</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="string">"pear"</span>, <span class="string">"mango"</span> -&gt; <span class="number">2</span>;</span><br><span class="line">            <span class="keyword">default</span> -&gt; &#123;</span><br><span class="line">                <span class="keyword">int</span> code = fruit.hashCode();</span><br><span class="line">                yield code; <span class="comment">// switch语句返回值</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;</span><br><span class="line">        System.out.println(<span class="string">"opt = "</span> + opt);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>由于<code>switch</code>表达式是作为Java 13的预览特性（Preview Language Features）实现的，编译的时候，我们还需要给编译器加上参数：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;</span><span class="bash"> javac --<span class="built_in">source</span> 13 --<span class="built_in">enable</span>-preview Main.java</span></span><br></pre></td></tr></table></figure>

<p>这样才能正常编译。</p>
<h3 id="while循环"><a href="#while循环" class="headerlink" title="while循环"></a><code>while</code>循环</h3><p>循环语句就是让计算机根据条件做循环计算，在条件满足时继续循环，条件不满足时退出循环。</p>
<p>例如，计算从1到100的和：</p>
<p>除了用数列公式外，完全可以让计算机做100次循环累加。因为计算机的特点是计算速度非常快，我们让计算机循环一亿次也用不到1秒，所以很多计算的任务，人去算是算不了的，但是计算机算，使用循环这种简单粗暴的方法就可以快速得到结果。</p>
<p>我们先看Java提供的<code>while</code>条件循环。它的基本用法是：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">while</span> (条件表达式) &#123;</span><br><span class="line">    循环语句</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 继续执行后续代码</span></span><br></pre></td></tr></table></figure>

<p><code>while</code>循环在每次循环开始前，首先判断条件是否成立。如果计算结果为<code>true</code>，就把循环体内的语句执行一遍，如果计算结果为<code>false</code>，那就直接跳到<code>while</code>循环的末尾，继续往下执行。</p>
<p>我们用while循环来累加1到100，可以这么写：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// while</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> sum = <span class="number">0</span>; <span class="comment">// 累加的和，初始化为0</span></span><br><span class="line">        <span class="keyword">int</span> n = <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">while</span> (n &lt;= <span class="number">100</span>) &#123; <span class="comment">// 循环条件是n &lt;= 100</span></span><br><span class="line">            sum = sum + n; <span class="comment">// 把n累加到sum中</span></span><br><span class="line">            n ++; <span class="comment">// n自身加1</span></span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(sum); <span class="comment">// 5050</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>注意到<code>while</code>循环是先判断循环条件，再循环，因此，有可能一次循环都不做。</p>
<p>对于循环条件判断，以及自增变量的处理，要特别注意边界条件。思考一下下面的代码为何没有获得正确结果：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// while</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> sum = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">int</span> n = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">while</span> (n &lt;= <span class="number">100</span>) &#123;</span><br><span class="line">            n ++;</span><br><span class="line">            sum = sum + n;</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(sum);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>如果循环条件永远满足，那这个循环就变成了死循环。死循环将导致100%的CPU占用，用户会感觉电脑运行缓慢，所以要避免编写死循环代码。</p>
<p>如果循环条件的逻辑写得有问题，也会造成意料之外的结果：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// while</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> sum = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">int</span> n = <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">while</span> (n &gt; <span class="number">0</span>) &#123;</span><br><span class="line">            sum = sum + n;</span><br><span class="line">            n ++;</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(n); <span class="comment">// -2147483648</span></span><br><span class="line">        System.out.println(sum);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p> 表面上看，上面的<code>while</code>循环是一个死循环，但是，Java的<code>int</code>类型有最大值，达到最大值后，再加1会变成负数，结果，意外退出了<code>while</code>循环。</p>
<h4 id="do-while循环"><a href="#do-while循环" class="headerlink" title="do while循环"></a><code>do while</code>循环</h4><p>在Java中，<code>while</code>循环是先判断循环条件，再执行循环。而另一种<code>do while</code>循环则是先执行循环，再判断条件，条件满足时继续循环，条件不满足时退出。它的用法是：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">do</span> &#123;</span><br><span class="line">    执行循环语句</span><br><span class="line">&#125; <span class="keyword">while</span> (条件表达式);</span><br></pre></td></tr></table></figure>

<p>可见，<code>do while</code>循环会至少循环一次。</p>
<p>我们把对1到100的求和用<code>do while</code>循环改写一下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// do-while</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> sum = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">int</span> n = <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">do</span> &#123;</span><br><span class="line">            sum = sum + n;</span><br><span class="line">            n ++;</span><br><span class="line">        &#125; <span class="keyword">while</span> (n &lt;= <span class="number">100</span>);</span><br><span class="line">        System.out.println(sum);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p> 使用<code>do while</code>循环时，同样要注意循环条件的判断。</p>
<h3 id="for循环"><a href="#for循环" class="headerlink" title="for循环"></a><code>for</code>循环</h3><p>除了<code>while</code>和<code>do while</code>循环，Java使用最广泛的是<code>for</code>循环。</p>
<p><code>for</code>循环的功能非常强大，它使用计数器实现循环。<code>for</code>循环会先初始化计数器，然后，在每次循环前检测循环条件，在每次循环后更新计数器。计数器变量通常命名为<code>i</code>。</p>
<p>我们把1到100求和用<code>for</code>循环改写一下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// for</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> sum = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i=<span class="number">1</span>; i&lt;=<span class="number">100</span>; i++) &#123;</span><br><span class="line">            sum = sum + i;</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(sum);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在<code>for</code>循环执行前，会先执行初始化语句<code>int i=1</code>，它定义了计数器变量<code>i</code>并赋初始值为<code>1</code>，然后，循环前先检查循环条件<code>i&lt;=100</code>，循环后自动执行<code>i++</code>，因此，和<code>while</code>循环相比，<code>for</code>循环把更新计数器的代码统一放到了一起。在<code>for</code>循环的循环体内部，不需要去更新变量<code>i</code>。</p>
<p>因此，<code>for</code>循环的用法是：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (初始条件; 循环检测条件; 循环后更新计数器) &#123;</span><br><span class="line">    <span class="comment">// 执行语句</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>如果我们要对一个整型数组的所有元素求和，可以用<code>for</code>循环实现：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// for</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span>[] ns = &#123; <span class="number">1</span>, <span class="number">4</span>, <span class="number">9</span>, <span class="number">16</span>, <span class="number">25</span> &#125;;</span><br><span class="line">        <span class="keyword">int</span> sum = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i=<span class="number">0</span>; i&lt;ns.length; i++) &#123;</span><br><span class="line">            System.out.println(<span class="string">"i = "</span> + i + <span class="string">", ns[i] = "</span> + ns[i]);</span><br><span class="line">            sum = sum + ns[i];</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(<span class="string">"sum = "</span> + sum);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>上面代码的循环条件是<code>i</code>。因为<code>ns</code>数组的长度是<code>5</code>，因此，当循环<code>5</code>次后，<code>i</code>的值被更新为<code>5</code>，就不满足循环条件，因此<code>for</code>循环结束。</p>
<p> 思考：如果把循环条件改为<code>i&lt;=ns.length</code>，会出现什么问题？</p>
<p>注意<code>for</code>循环的初始化计数器总是会被执行，并且<code>for</code>循环也可能循环0次。</p>
<p>使用<code>for</code>循环时，千万不要在循环体内修改计数器！在循环体中修改计数器常常导致莫名其妙的逻辑错误。对于下面的代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// for</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span>[] ns = &#123; <span class="number">1</span>, <span class="number">4</span>, <span class="number">9</span>, <span class="number">16</span>, <span class="number">25</span> &#125;;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i=<span class="number">0</span>; i&lt;ns.length; i++) &#123;</span><br><span class="line">            System.out.println(ns[i]);</span><br><span class="line">            i = i + <span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>虽然不会报错，但是，数组元素只打印了一半，原因是循环内部的<code>i = i + 1</code>导致了计数器变量每次循环实际上加了<code>2</code>（因为<code>for</code>循环还会自动执行<code>i++</code>）。因此，在<code>for</code>循环中，不要修改计数器的值。计数器的初始化、判断条件、每次循环后的更新条件统一放到<code>for()</code>语句中可以一目了然。</p>
<p>如果希望只访问索引为奇数的数组元素，应该把<code>for</code>循环改写为：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span>[] ns = &#123; <span class="number">1</span>, <span class="number">4</span>, <span class="number">9</span>, <span class="number">16</span>, <span class="number">25</span> &#125;;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i=<span class="number">0</span>; i&lt;ns.length; i=i+<span class="number">2</span>) &#123;</span><br><span class="line">    System.out.println(ns[i]);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>通过更新计数器的语句<code>i=i+2</code>就达到了这个效果，从而避免了在循环体内去修改变量<code>i</code>。</p>
<p>使用<code>for</code>循环时，计数器变量<code>i</code>要尽量定义在<code>for</code>循环中：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span>[] ns = &#123; <span class="number">1</span>, <span class="number">4</span>, <span class="number">9</span>, <span class="number">16</span>, <span class="number">25</span> &#125;;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i=<span class="number">0</span>; i&lt;ns.length; i++) &#123;</span><br><span class="line">    System.out.println(ns[i]);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 无法访问i</span></span><br><span class="line"><span class="keyword">int</span> n = i; <span class="comment">// compile error!</span></span><br></pre></td></tr></table></figure>

<p>如果变量<code>i</code>定义在<code>for</code>循环外：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span>[] ns = &#123; <span class="number">1</span>, <span class="number">4</span>, <span class="number">9</span>, <span class="number">16</span>, <span class="number">25</span> &#125;;</span><br><span class="line"><span class="keyword">int</span> i;</span><br><span class="line"><span class="keyword">for</span> (i=<span class="number">0</span>; i&lt;ns.length; i++) &#123;</span><br><span class="line">    System.out.println(ns[i]);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 仍然可以使用i</span></span><br><span class="line"><span class="keyword">int</span> n = i;</span><br></pre></td></tr></table></figure>

<p>那么，退出<code>for</code>循环后，变量<code>i</code>仍然可以被访问，这就破坏了变量应该把访问范围缩到最小的原则。</p>
<h4 id="灵活使用for循环"><a href="#灵活使用for循环" class="headerlink" title="灵活使用for循环"></a>灵活使用for循环</h4><p><code>for</code>循环还可以缺少初始化语句、循环条件和每次循环更新语句，例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 不设置结束条件:</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i=<span class="number">0</span>; ; i++) &#123;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 不设置结束条件和更新语句:</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i=<span class="number">0</span>; ;) &#123;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 什么都不设置:</span></span><br><span class="line"><span class="keyword">for</span> (;;) &#123;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>通常不推荐这样写，但是，某些情况下，是可以省略<code>for</code>循环的某些语句的。</p>
<h4 id="for-each循环"><a href="#for-each循环" class="headerlink" title="for each循环"></a>for each循环</h4><p><code>for</code>循环经常用来遍历数组，因为通过计数器可以根据索引来访问数组的每个元素：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span>[] ns = &#123; <span class="number">1</span>, <span class="number">4</span>, <span class="number">9</span>, <span class="number">16</span>, <span class="number">25</span> &#125;;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i=<span class="number">0</span>; i&lt;ns.length; i++) &#123;</span><br><span class="line">    System.out.println(ns[i]);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>但是，很多时候，我们实际上真正想要访问的是数组每个元素的值。Java还提供了另一种<code>for each</code>循环，它可以更简单地遍历数组：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// for each</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span>[] ns = &#123; <span class="number">1</span>, <span class="number">4</span>, <span class="number">9</span>, <span class="number">16</span>, <span class="number">25</span> &#125;;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> n : ns) &#123;</span><br><span class="line">            System.out.println(n);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>和<code>for</code>循环相比，<code>for each</code>循环的变量n不再是计数器，而是直接对应到数组的每个元素。<code>for each</code>循环的写法也更简洁。但是，<code>for each</code>循环无法指定遍历顺序，也无法获取数组的索引。</p>
<p>除了数组外，<code>for each</code>循环能够遍历所有“可迭代”的数据类型，包括后面会介绍的<code>List</code>、<code>Map</code>等。</p>
<h3 id="break和continue"><a href="#break和continue" class="headerlink" title="break和continue"></a><code>break</code>和<code>continue</code></h3><p>无论是<code>while</code>循环还是<code>for</code>循环，有两个特别的语句可以使用，就是<code>break</code>语句和<code>continue</code>语句。</p>
<h4 id="break"><a href="#break" class="headerlink" title="break"></a><code>break</code></h4><p>在循环过程中，可以使用<code>break</code>语句跳出当前循环。我们来看一个例子：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// break</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> sum = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i=<span class="number">1</span>; ; i++) &#123;</span><br><span class="line">            sum = sum + i;</span><br><span class="line">            <span class="keyword">if</span> (i == <span class="number">100</span>) &#123;</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(sum);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>使用<code>for</code>循环计算从1到100时，我们并没有在<code>for()</code>中设置循环退出的检测条件。但是，在循环内部，我们用<code>if</code>判断，如果<code>i==100</code>，就通过<code>break</code>退出循环。</p>
<p>因此，<code>break</code>语句通常都是配合<code>if</code>语句使用。要特别注意，<code>break</code>语句总是跳出自己所在的那一层循环。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// break</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i=<span class="number">1</span>; i&lt;=<span class="number">10</span>; i++) &#123;</span><br><span class="line">            System.out.println(<span class="string">"i = "</span> + i);</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> j=<span class="number">1</span>; j&lt;=<span class="number">10</span>; j++) &#123;</span><br><span class="line">                System.out.println(<span class="string">"j = "</span> + j);</span><br><span class="line">                <span class="keyword">if</span> (j &gt;= i) &#123;</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// break跳到这里</span></span><br><span class="line">            System.out.println(<span class="string">"breaked"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>上面的代码是两个<code>for</code>循环嵌套。因为<code>break</code>语句位于内层的<code>for</code>循环，因此，它会跳出内层<code>for</code>循环，但不会跳出外层<code>for</code>循环。</p>
<h4 id="continue"><a href="#continue" class="headerlink" title="continue"></a><code>continue</code></h4><p><code>break</code>会跳出当前循环，也就是整个循环都不会执行了。而<code>continue</code>则是提前结束本次循环，直接继续执行下次循环。我们看一个例子：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// continue</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> sum = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i=<span class="number">1</span>; i&lt;=<span class="number">10</span>; i++) &#123;</span><br><span class="line">            System.out.println(<span class="string">"begin i = "</span> + i);</span><br><span class="line">            <span class="keyword">if</span> (i % <span class="number">2</span> == <span class="number">0</span>) &#123;</span><br><span class="line">                <span class="keyword">continue</span>; <span class="comment">// continue语句会结束本次循环</span></span><br><span class="line">            &#125;</span><br><span class="line">            sum = sum + i;</span><br><span class="line">            System.out.println(<span class="string">"end i = "</span> + i);</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(sum); <span class="comment">// 25</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>注意观察<code>continue</code>语句的效果。当<code>i</code>为奇数时，完整地执行了整个循环，因此，会打印<code>begin i=1</code>和<code>end i=1</code>。在i为偶数时，<code>continue</code>语句会提前结束本次循环，因此，会打印<code>begin i=2</code>但不会打印<code>end i = 2</code>。</p>
<p>在多层嵌套的循环中，<code>continue</code>语句同样是结束本次自己所在的循环。</p>
<h3 id="throw语句"><a href="#throw语句" class="headerlink" title="throw语句"></a><code>throw</code>语句</h3><p>异常是一种信号，表明发生了某种异常状况或错误。</p>
<ul>
<li>抛出异常的目的是发出信号，表示有异常状况发生。</li>
<li>捕获异常的目的是处理异常，使用必要的操作修复。</li>
</ul>
<p>在 Java 中，throw 语句用于抛出异常：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">throw</span> expression;</span><br></pre></td></tr></table></figure>

<p>expression 的计算结果必须是一个异常对象，说明发生了什么异常或错误。稍后会详细介绍异常的种类，现在你只需知道，异常通过有点特殊的对象表示。下面是抛出异常的示例代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">double</span> <span class="title">factorial</span><span class="params">(<span class="keyword">int</span> x)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (x &lt; <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> IllegalArgumentException(<span class="string">"x must be &gt;= 0"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">double</span> fact;</span><br><span class="line">    <span class="keyword">for</span> (fact = <span class="number">1.0</span>; x &gt; <span class="number">1</span>; fact *= x, x--) &#123;</span><br><span class="line">        System.out.print(x + <span class="string">","</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    System.out.println();</span><br><span class="line">    <span class="keyword">return</span> fact;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>Java 解释器执行 throw 语句时，会立即停止常规的程序执行，开始寻找能捕获或处理异常的异常处理程序。异常处理程序使用 <code>try</code>/<code>catch</code>/<code>finally</code> 语句编写。</p>
<p>Java解释器先在当前代码块中查找异常处理程序，如果有，解释器会退出这个代码块，开始执行异常处理代码。异常处理程序执行完毕后，解释器会继续执行处理程序后的语句。</p>
<p>如果当前代码块中没有适当的异常处理程序，解释器会在外层代码块中寻找，直到找到为止。如果方法中没有能处理 <code>throw</code> 语句抛出的异常的异常处理程序，解释器会停止运行当前方法，返回调用这个方法的地方，开始在调用方法的代码块中寻找异常处理程序。</p>
<p>Java通过这种方式，通过方法的词法结构不断向上冒泡，顺着解释器的调用堆栈一直向上寻找。如果一直没有捕获异常，就会冒泡到程序的 <code>main()</code> 方法。如果在 <code>main()</code> 方法中也没有处理异常，Java 解释器会打印一个错误消息，还会打印一个堆栈跟踪，指明这个异常在哪里发生，然后退出。</p>
<h3 id="assert语句"><a href="#assert语句" class="headerlink" title="assert语句"></a><code>assert</code>语句</h3><p><code>assert</code> 语句用来验证 Java 代码的设计假想。断言（assertion）由 <code>assert</code> 关键字和布尔表达式组成，程序员认为布尔表达式的计算结果始终应该为 true。默认情况下断言未启用，assert 语句什么作用也没有。</p>
<p>不过，可以启用断言，作为一种调试工具。启用后，<code>assert</code> 语句会计算表达式。如果表达式的计算结果确是 true，<code>assert</code> 语句什么也不做；如果计算结果是 false，断言失败，<code>assert</code> 语句抛出 <code>java.lang.AssertionError</code> 异常。</p>
<blockquote>
<p>在 JDK 库之外，极少使用 assert 语句。用它测试大多数应用都不灵便，一般的开发者很少使用，不过有时用来现场调试复杂的多线程应用。</p>
</blockquote>
<p><code>assert</code> 语句可以包含可选的第二个表达式，使用冒号和第一个表达式分开。如果启用了断言，而且第一个表达式的计算结果为 false，那么第二个表达式的值会作为错误代码或错误消息传给 AssertionError() 构造方法。assert 语句的完整句法如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">assert</span> assertion;</span><br><span class="line"><span class="comment">//或者</span></span><br><span class="line"><span class="keyword">assert</span> assertion : errorcode;</span><br></pre></td></tr></table></figure>



<h3 id="synchronized语句"><a href="#synchronized语句" class="headerlink" title="synchronized语句"></a><code>synchronized</code>语句</h3><p>Java 一直支持多线程编程，但并发编程不容易，有很多难以捉摸的地方。具体而言，处理多线程时，经常必须避免多个线程同时修改同一个对象，以防对象的状态有冲突。Java 提供的 <code>synchronized</code> 语句可以帮助程序员，避免发生冲突。<code>synchronized</code> 语句的句法为：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">synchronized</span> ( expression ) &#123; </span><br><span class="line">   statements </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><code>expression</code> 表达式的计算结果必须是一个对象或数组。<code>statements</code> 是能导致破坏的代码块，必须放在花括号里。</p>
<p>执行语句块之前，Java 解释器先为 <code>expression</code> 计算得到的对象或数组获取一个排它锁（exclusive lock），直到语句块执行完毕后再释放。只要某个线程拥有对象的排它锁，其他线程就不能再获取这个锁。</p>
<p>在 Java 中，<code>synchronized</code> 关键字还可以作为方法的修饰符。应用于方法时，<code>synchronized</code>关键字指明整个方法都被锁定。如果 <code>synchronized</code> 关键字应用于类方法（静态方法），执行方法前，Java 会先为这个类获取一个排它锁。如果 <code>synchronized</code> 关键字应用于实例方法，Java 为类的实例获取一个排它锁。</p>
<h3 id="try-catch-finally语句"><a href="#try-catch-finally语句" class="headerlink" title="try/catch/finally语句"></a><code>try</code>/<code>catch</code>/<code>finally</code>语句</h3><p>Java 有两种稍微不同的异常处理机制。经典形式是使用 <code>try</code>/<code>catch</code>/<code>finally</code> 语句。这个语句的 <code>try</code> 子句是可能抛出异常的代码块。<code>try</code> 代码块后面是零个或多个 <code>catch</code> 子句，每个子句用于处理特定类型的异常，而且能处理多个不同类型的异常。如果 <code>catch</code> 块要处理多个异常，使用 | 符号分隔各个不同的异常。<code>catch</code> 子句后面是一个可选的 <code>finally</code> 块，包含清理代码，不管 <code>try</code> 块中发生了什么，始终都会执行。</p>
<blockquote>
<p><code>catch</code> 和 <code>finally</code> 子句都是可选的，但每个 <code>try</code> 块都必须有这两个子句中的一个。<code>try</code>、<code>catch</code> 和 <code>finally</code> 块都放在花括号里。花括号是句法必须的一部分，即使子句只包含一个语句也不能省略</p>
</blockquote>
<h4 id="try子句"><a href="#try子句" class="headerlink" title="try子句"></a><code>try</code>子句</h4><p><code>try</code> 子句的作用很简单，组建一段代码，其中有异常需要处理，或者因某种原因终止执行后需要使用特殊的代码清理。<code>try</code> 子句本身没什么用，异常处理和清理操作在 <code>catch</code> 和<code>finally</code> 子句中进行。</p>
<h4 id="catch子句"><a href="#catch子句" class="headerlink" title="catch子句"></a><code>catch</code>子句</h4><p><code>try</code> 块后面可以跟着零个或多个 <code>catch</code> 子句，指定处理各种异常的代码。每个 <code>catch</code> 子句只有一个参数（可以使用特殊的 <code>|</code> 句法指明 <code>catch</code> 块能处理多种异常类型），指定这个子句能处理的异常类型，以及一个名称，用来引用当前处理的异常对象。<code>catch</code> 块能处理的类型必须是 <code>Throwable</code> 的子类。</p>
<p>有异常抛出时，Java 解释器会寻找一个 <code>catch</code> 子句，它的参数要和异常对象的类型相同，或者是这个类型的子类。解释器会调用它找到的第一个这种 <code>catch</code> 子句。<code>catch</code> 块中的代码应该执行处理异常状况所需的任何操作。假如异常是 <code>java.io.FileNotFoundException</code>，此时或许要请求用户检查拼写，然后重试。</p>
<p>不是所有可能抛出的异常都要有一个 <code>catch</code> 子句处理，有些情况下，正确的处理方式是让异常向上冒泡，由调用方法捕获。还有些情况，例如表示程序错误的<code>NullPointerException</code> 异常，正确的处理方式或许是完全不捕获，随它冒泡，让 Java 解释器退出，打印堆栈跟踪和错误消息。</p>
<h4 id="finally子句"><a href="#finally子句" class="headerlink" title="finally子句"></a><code>finally</code>子句</h4><p><code>finnaly</code> 子句放在 <code>try</code> 子句后面，一般用来执行清理操作（例如关闭文件和网络连接）。<code>finally</code> 子句很有用，因为不管 <code>try</code> 块中的代码以何种方式结束执行，只要有代码执行，<code>finally</code> 子句中的代码就会执行。事实上，只有一种方法能让 <code>try</code> 子句退出而不执行<code>finally</code> 子句——调用 <code>System.exit()</code> 方法，让 Java 解释器停止运行。</p>
<p>正常情况下，执行到 <code>try</code> 块的末尾后会继续执行 <code>finally</code> 块，做必要的清理工作。如果因为 <code>return</code>、<code>continue</code> 或 <code>break</code> 语句而离开 <code>try</code> 块，会先执行 <code>finally</code> 块，然后再转向新的目标代码。</p>
<p>如果 <code>try</code> 块抛出了异常，而且有处理该异常的 <code>catch</code> 块，那么先执行 <code>catch</code> 块，然后在执行 <code>finally</code> 块。如果本地没有能处理该异常的 <code>catch</code> 块，先执行 <code>finally</code> 块，然后再向上冒泡到能处理该异常最近的 <code>catch</code> 子句。</p>
<p>如果 <code>finally</code> 块使用 <code>return</code>、<code>continue</code>、<code>break</code> 或 <code>throw</code> 语句，或者调用的方法抛出了异常，从而转移了控制权，那么待转移的控制权中止，改为执行新的控制权转移。例如，如果 <code>finally</code> 子句抛出了异常，这个异常会取代任何正在抛出的异常。如果 <code>finally</code> 子句使用了 <code>return</code> 语句，就算抛出的异常还没处理，方法也会正常返回。</p>
<p><code>try</code> 和 <code>finally</code> 子句可以放在一起使用，不处理异常，也没有 <code>catch</code> 子句。 此时，<code>finally</code> 块只是负责清理的代码，不管 <code>try</code> 子句中有没有 <code>break</code>、<code>continue</code> 或 <code>return</code> 语句，都会执行。</p>
<h3 id="处理资源的try语句"><a href="#处理资源的try语句" class="headerlink" title="处理资源的try语句"></a>处理资源的try语句</h3><p>Java（从第 7 版起）提供了一种很有用的机制，能自动关闭需要清理的资源——处理资源的 <code>try</code> 语句（try-with-resources，TWR）。下面的示例展示了如何使用 <code>FileInputStream</code> 类打开文件（得到的对象需要清理）：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">try</span> (InputStream is = <span class="keyword">new</span> FileInputStream(<span class="string">"/Users/ben/details.txt"</span>)) &#123; </span><br><span class="line">  <span class="comment">// ……处理这个文件 </span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这种新型 try 语句的参数都是需要清理的对象（这些对象必须实现 <code>AutoCloseable</code> 接口）。这些对象的作用域在 <code>try</code> 块中，不管 <code>try</code>块以何种方式退出，都会自动清理。开发者无需编写任何 <code>catch</code> 或 <code>finally</code> 块，Java 编译器会自动插入正确的清理代码。</p>
<h2 id="方法-1"><a href="#方法-1" class="headerlink" title="方法"></a>方法</h2><p>方法是有名称的 Java 语句序列，可被其他 Java 代码调用。调用方法时，可以传入零个或多个值，这些值叫<strong>参数</strong>。方法执行一些计算，还可以返回一个值。</p>
<h3 id="定义方法"><a href="#定义方法" class="headerlink" title="定义方法"></a>定义方法</h3><p>方法主体就是放在花括号里的任意语句序列。更有趣的是方法的<strong>签名</strong>（signature）， 签名指定下述内容：</p>
<ul>
<li>方法的名称；</li>
<li>方法所用参数的数量、顺序、类型和名称；</li>
<li>方法的返回值类型；</li>
<li>方法能抛出的已检异常（签名还能列出未检异常，不过不是必需的）；</li>
<li>提供方法额外信息的多个方法修饰符。</li>
</ul>
<p>方法签名定义了调用方法之前需要知道的一切信息，是方法的规范，而且定义了方法的API。</p>
<ul>
<li>若想使用 Java 平台的在线 API 参考指南，需要知道如何阅读方法签名。</li>
<li>若想编写Java 程序，需要知道如何定义自己的方法。</li>
</ul>
<p>方法都以方法签名开头。方法签名的格式如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">modifiers type <span class="title">name</span> <span class="params">( paramlist )</span> [ <span class="keyword">throws</span> exceptions ]</span></span><br></pre></td></tr></table></figure>

<p>签名（方法规范）后面是方法主体（方法的实现），即放在花括号里的 Java 语句序列。</p>
<ul>
<li><code>modifiers</code> 是零个或多个特殊的修饰符关键字，之间使用空格分开。例如，声明方法时可以使用 <code>public</code> 和 <code>static</code> 修饰符。</li>
<li><code>type</code> 指明方法返回值的类型。如果方法没有返回值，<code>type</code> 必须是 <code>void</code>。如果声明方法时指定了返回类型，就必须包含一个 <code>return</code> 语句，返回一个符合（或能转换为）所声明类型的值。</li>
<li><code>name</code>，即方法名。方法名和变量名一样，也是 Java 标识符。定义多个同名方法叫方法重载（method overloading）。</li>
<li>定义方法时，方法名后一定是方法的形参列表（parameters list），而且必须放在括号里。形参列表定义零个或多个传入方法的实参（argument）。如果有形参的话，每个形参都包含类型和名称，如果有多个形参，形参之间使用逗号分开。调用方法时，传入的实参值必须和该方法签名中定义的形参数量、类型和顺序匹配。传入的值不一定要和签名中指定的类型一样，但是必须能不经校正转换为对应的类型。</li>
<li>方法签名的最后一部分是 <code>throws</code> 子句，列出方法能抛出的已检异常（checked exception）。已检异常是一系列异常类，必须在能抛出它们的方法中使用 <code>throws</code> 子句列出。<ul>
<li>如果方法使用 <code>throw</code> 语句抛出一个已检异常，或者调用的其他方法抛出一个没有捕获或处理的已检异常，声明这个方法时就必须指明能抛出这个异常。</li>
<li>如果方法能抛出一个或多个已检异常，要在参数列表后面使用 <code>throws</code> 关键字指明能抛出的异常类。</li>
<li>如果方法不会抛出异常，无需使用 <code>throws</code> 关键字。</li>
<li>如果方法抛出的异常类型不止一个，要使用逗号分隔异常类的名称。</li>
</ul>
</li>
</ul>
<blockquote>
<p>抽象方法没有实现部分，方法主体使用一个分号表示。</p>
</blockquote>
<blockquote>
<p>构造方法是一段类似方法的代码，用于初始化新建的对象。</p>
</blockquote>
<blockquote>
<p>方法签名中可能包含类型变量声明，这种方法叫泛型方法（generic method）。</p>
</blockquote>
<p>下面是一些方法定义示例，都以签名开头，后面跟着方法主体：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 这个方法传入的是字符串数组，没有返回值 </span></span><br><span class="line"><span class="comment">// 所有Java程序的入口都是这个名称和签名 </span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123; </span><br><span class="line">    <span class="keyword">if</span> (args.length &gt; <span class="number">0</span>) &#123;</span><br><span class="line">        System.out.println(<span class="string">"Hello "</span> + args[<span class="number">0</span>]);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">"Hello world"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 这个方法传入两个double类型的参数，返回一个double类型的数字 </span></span><br><span class="line"><span class="function"><span class="keyword">static</span> <span class="keyword">double</span> <span class="title">distanceFromOrigin</span><span class="params">(<span class="keyword">double</span> x, <span class="keyword">double</span> y)</span> </span>&#123; </span><br><span class="line">     <span class="keyword">return</span> Math.sqrt(x*x + y*y); </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 这是抽象方法，没有主体 </span></span><br><span class="line"><span class="comment">// 注意，调用这个方法时可能会抛出异常 </span></span><br><span class="line"><span class="function"><span class="keyword">protected</span> <span class="keyword">abstract</span> String <span class="title">readText</span><span class="params">(File f, String encoding)</span> </span></span><br><span class="line"><span class="function">    <span class="keyword">throws</span> FileNotFoundException, UnsupportedEncodingException</span>;</span><br></pre></td></tr></table></figure>

<p>和某些其他语言不同，Java 没有匿名方法。不过，Java 8 引入了 <code>lambda</code> 表达式，作用类似于匿名方法，但是 Java 运行时会自动把 <code>lambda</code> 表达式转换成适当的具名方法，</p>
<h3 id="方法修饰符"><a href="#方法修饰符" class="headerlink" title="方法修饰符"></a>方法修饰符</h3><p>方法的修饰符包含零个或多个修饰符关键字，例如 <code>public</code>、<code>static</code> 或 <code>abstract</code>。</p>
<h4 id="abstract"><a href="#abstract" class="headerlink" title="abstract"></a><code>abstract</code></h4><p>使用 <code>abstract</code> 修饰的方法没有实现主体。组成普通方法主体的花括号和 Java 语句使用一个分号代替。如果类中有使用 <code>abstract</code> 修饰的方法，类本身也必须使用 <code>abstract</code> 声明。这种类不完整，不能实例化。</p>
<h4 id="final"><a href="#final" class="headerlink" title="final"></a><code>final</code></h4><p>使用 <code>final</code> 修饰的方法不能被子类覆盖或隐藏，能获得普通方法无法得到的编译器优化。所有使用 <code>private</code> 修饰的方法都隐式添加了 <code>final</code> 修饰符；使用 <code>final</code> 声明的任何类，其中的所有方法也都隐式添加 <code>final</code> 修饰符。</p>
<h4 id="native"><a href="#native" class="headerlink" title="native"></a><code>native</code></h4><p><code>native</code> 修饰符表明方法的实现使用某种“本地”语言编写，例如 C 语言，并且开放给Java 程序使用。<code>native</code> 修饰的方法和 <code>abstract</code> 修饰的方法一样，没有主体：花括号使用一个分号代替。</p>
<blockquote>
<p>Java 刚出现时，使用 <code>native</code> 修饰方法有时是为了提高效率。现在几乎不需要这么做了。现在，使用 <code>native</code> 修饰方法的目的是，把 Java 代码集成到现有的 C 或 C++ 库中。<code>native</code> 修饰的方法和所在平台无关，如何把实现和方法声明所在的 Java 类链接起来，取决于 Java 虚拟机的实现方式。</p>
</blockquote>
<h4 id="public、protected、private"><a href="#public、protected、private" class="headerlink" title="public、protected、private"></a><code>public</code>、<code>protected</code>、<code>private</code></h4><p>些访问修饰符指定方法是否能在定义它的类之外使用，或者能在何处使用。</p>
<h4 id="static"><a href="#static" class="headerlink" title="static"></a><code>static</code></h4><p>使用 <code>static</code> 声明的方法是类方法，关联在类自己身上，而不是类的实例身上</p>
<h4 id="strictfp"><a href="#strictfp" class="headerlink" title="strictfp"></a><code>strictfp</code></h4><p>在这个很少使用的奇怪修饰符中，fp 的意思是“浮点”（floating point）。一般情况下，Java 会利用运行时所在平台的浮点硬件提供的可用扩展精度。添加这个关键字后，运行<code>strictfp</code> 修饰的方法时，Java 会严格遵守标准，而且就算结果不精确，也只使用 32 位或 64 位浮点数格式进行浮点运算。</p>
<h4 id="synchronized"><a href="#synchronized" class="headerlink" title="synchronized"></a><code>synchronized</code></h4><p><code>synchronized</code> 修饰符的作用是实现线程安全的方法。线程调用 <code>synchronized</code> 修饰的方法之前，必须先为方法所在的类（针对 static 修饰的方法）或对应的类实例（针对没使用 static 修饰的方法）获取一个锁，避免两个线程同时执行该方法。</p>
<p><code>synchronized</code> 修饰符是实现的细节（因为方法可以通过其他方式实现线程安全），不是方法规范或 API 的正式组成部分。好的文档应该明确说明方法是否线程安全，使用多线程程序时不能依赖于是否有 <code>synchronized</code> 关键字。</p>
<h3 id="已检异常和未检异常"><a href="#已检异常和未检异常" class="headerlink" title="已检异常和未检异常"></a>已检异常和未检异常</h3><p>Java 的异常处理机制会区分两种不同的异常类型：已检异常和未检异常。</p>
<p>已检异常和未检异常之间的区别在于异常在什么情况下抛出。已检异常在明确的特定情况下抛出，经常是应用能部分或完全恢复的情况。</p>
<p>例如，某段代码要在多个可能的目录中寻找配置文件。如果试图打开的文件不在某个目录中，就会抛出 <code>FileNotFoundException</code> 异常。在这个例子中，我们想捕获这个异常，然后在文件可能出现的下一个位置继续尝试。也就是说，虽然文件不存在是异常状况，但可以从中恢复，这是意料之中的失败。</p>
<p>然而，在 Java 环境中有些失败是无法预料的，这些失败可能是由运行时条件或滥用库代码导致的。例如，无法正确预知 <code>OutOfMemoryError</code> 异常；又如，把无效的 null 传给使用对象或数组的方法，会抛出 <code>NullPointerException</code> 异常。</p>
<p>这些是未检异常。基本上任何方法在任何时候都可能抛出未检异常。这是 Java 环境中的墨菲定律：“会出错的事总会出错。”从未检异常中恢复，虽说不是不可能，但往往很难，因为完全不可预知。</p>
<p>若想区分已检异常和未检异常，记住两点：异常是 <code>Throwable</code> 对象，而且异常主要分为两类，通过 <code>Error</code> 和 <code>Exception</code> 子类标识。只要异常对象是 <code>Error</code> 类，就是未检异常。<code>Exception</code> 类还有一个子类 <code>RuntimeException</code>，<code>RuntimeException</code> 类的所有子类都属于未检异常。除此之外，都是已检异常。</p>
<p><strong>处理已检异常</strong></p>
<p>Java 为已检异常和未检异常制定了不同的规则。如果定义的方法会抛出已检异常，就必须在方法签名的 <code>throws</code> 子句中声明这个异常。Java 编译器会检查方法签名，确保的确声明了；如果没声明，会导致编译出错（所以才叫“已检异常”）。</p>
<p>就算自己从不抛出已检异常，有时也必须使用 <code>throws</code> 子句声明已检异常。如果方法中调用了会抛出已检异常的方法，要么加入异常处理代码处理这个异常，要么使用 <code>throws</code> 子句声明这个方法也能抛出这个异常。</p>
<p>例如，下述方法使用标准库中的 java.net 和 URL 类访问网页，尝试估算网页的大小。所用的方法和构造方法会抛出各种 <code>java.io.IOException</code> 异常对象，所以在 <code>throws</code> 子句中声明了：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="title">estimateHomepageSize</span><span class="params">(String host)</span> <span class="keyword">throws</span> IOException </span>&#123; </span><br><span class="line">    URL url = <span class="keyword">new</span> URL(<span class="string">"htp://"</span>+ host +<span class="string">"/"</span>); </span><br><span class="line">    <span class="keyword">try</span> (InputStream in = url.openStream()) &#123; </span><br><span class="line">        <span class="keyword">return</span> in.available(); </span><br><span class="line">    &#125; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>其实，上述代码有个问题：协议名拼写错了——没有名为 htp:// 的协议。所以，<code>estimate-HomepageSize()</code> 方法会一直失败，抛出 <code>MalformedURLException</code> 异常。</p>
<p>你怎么知道要调用的方法会抛出已检异常呢？可以查看这个方法的签名。如果签名中没有，但又必须处理或声明调用的方法抛出的异常时，Java 编译器会（通过编译错误消息）告诉你。</p>
<h3 id="变长参数列表"><a href="#变长参数列表" class="headerlink" title="变长参数列表"></a>变长参数列表</h3><p>方法可以声明为接受数量不定的参数，调用时也可以传入数量不定的参数。这种方法一般叫作变长参数方法。格式化打印方法 <code>System.out.printf()</code> 和 String 类相关的 <code>format()</code> 方法，以及 <code>java.lang.reflect</code> 中反射 API 的一些重要方法，都使用变长参数。</p>
<p>变长参数列表的声明方式为，在方法最后一个参数的类型后面加上省略号（<code>...</code>），指明最后一个参数可以重复零次或多次。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">max</span><span class="params">(<span class="keyword">int</span> first, <span class="keyword">int</span>... rest)</span> </span>&#123; </span><br><span class="line">    <span class="comment">/* 暂时省略主体 */</span> </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>变长参数方法纯粹由编译器处理，把数量不定的参数转换为一个数组。对 Java 运行时来说，上面的 <code>max()</code> 方法和下面这个没有区别：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">max</span><span class="params">(<span class="keyword">int</span> first, <span class="keyword">int</span>[] rest)</span> </span>&#123; </span><br><span class="line">    <span class="comment">/* 暂时省略主体 */</span> </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>把变长参数方法的签名转换为真正的签名，只需把 <code>...</code> 换成 <code>[]</code>。记住，参数列表中只能有一个省略号，而且只能出现在最后一个参数中。</p>
<p>下面填充 <code>max()</code> 方法的主体：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">max</span><span class="params">(<span class="keyword">int</span> first, <span class="keyword">int</span>... rest)</span> </span>&#123; </span><br><span class="line">    <span class="keyword">int</span> max = first; </span><br><span class="line">    <span class="comment">// 合法，因为rest其实就是数组</span></span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i : rest) &#123;  </span><br><span class="line">        <span class="keyword">if</span> (i &gt; max) max = i; </span><br><span class="line">    &#125; </span><br><span class="line">    <span class="keyword">return</span> max; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>声明这个 <code>max()</code> 方法时指定了两个参数，第一个是普通的 int 类型值，但是第二个可以重复零次或多次。下面对 <code>max()</code> 方法的调用都是合法的：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">max(<span class="number">0</span>) </span><br><span class="line">max(<span class="number">1</span>, <span class="number">2</span>) </span><br><span class="line">max(<span class="number">16</span>, <span class="number">8</span>, <span class="number">4</span>, <span class="number">2</span>, <span class="number">1</span>)</span><br></pre></td></tr></table></figure>

<p>因为变长参数方法被编译成接受数组参数的方法，所以在编译对这类方法的调用得到的代码中，包含创建和初始化这个数组的代码。因此，调用 <code>max(1,2,3)</code> 被编译成：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">max(<span class="number">1</span>, <span class="keyword">new</span> <span class="keyword">int</span>[] &#123; <span class="number">2</span>, <span class="number">3</span> &#125;)</span><br></pre></td></tr></table></figure>

<p>其实，如果参数的方法已经存储在数组中，完全可以直接把数组传给变长参数方法，而不用把数组中的元素取出来一个一个传入。<code>...</code> 参数可以看成一个数组。不过，反过来就不行了：<strong>只有</strong>使用省略号声明为变长参数方法，才能使用变长参数方法调用的句法。</p>
<h2 id="类和对象"><a href="#类和对象" class="headerlink" title="类和对象"></a>类和对象</h2><p>类是一段代码的名称，其中包含很多保存数据值的字段和操作这些值的方法。类是 Java 支持的五种引用类型之一，而且是最重要的一种。类是继方法之后的另一种高级句法。</p>
<p>关于类最重要的事情是，它们定义了一种新数据类型。例如，可以定义一个名为 Point 的类，表示笛卡尔二维坐标系中的数据点。这个类可能会定义两个字段，保存点的 x 和 y 坐标，还可能会定义处理和操作点的方法。Point 类就是一个新数据类型。</p>
<p>谈论数据类型时，要把数据类型和数据类型表示的值区分开，这一点很重要。char 是一种数据类型，用于表示 Unicode 字符。但是一个 char 类型的值表示某个具体的字符。类是一种数据类型，而类表示的值是对象。我们使用“类”这个名称的原因是，每个类定义一种对象。Point 类是一种数据类型，用于表示 (x, y) 点，而 Point 对象表示某个具体的 (x, y)点。正如你想得那样，类和类的对象联系紧密。</p>
<h3 id="定义类"><a href="#定义类" class="headerlink" title="定义类"></a>定义类</h3><p>前面讨论的 Point 类可以使用下面的方式定义：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/** 表示笛卡尔坐标系中的(x,y)点 */</span> </span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Point</span> </span>&#123; </span><br><span class="line">     <span class="comment">// 点的坐标 </span></span><br><span class="line">     <span class="keyword">public</span> <span class="keyword">double</span> x, y; </span><br><span class="line">    <span class="comment">// 初始化字段的构造方法</span></span><br><span class="line">     <span class="function"><span class="keyword">public</span> <span class="title">Point</span><span class="params">(<span class="keyword">double</span> x, <span class="keyword">double</span> y)</span> </span>&#123;     </span><br><span class="line">         <span class="keyword">this</span>.x = x; <span class="keyword">this</span>.y = y; </span><br><span class="line">     &#125; </span><br><span class="line">    <span class="comment">// 操作x和y字段的方法</span></span><br><span class="line">     <span class="function"><span class="keyword">public</span> <span class="keyword">double</span> <span class="title">distanceFromOrigin</span><span class="params">()</span> </span>&#123;   </span><br><span class="line">         <span class="keyword">return</span> Math.sqrt(x*x + y*y); </span><br><span class="line">     &#125; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这个类的定义保存在一个名为 Point.java 的文件中，然后编译成一个名为 Point.class 的文件，供 Java 程序和其他类使用。</p>
<p>记住，你不需要定义想在 Java 程序中使用的每个类。Java 平台包含上千个预先定义好的类，在每台运行 Java 的电脑中都能使用。</p>
<h3 id="创建对象"><a href="#创建对象" class="headerlink" title="创建对象"></a>创建对象</h3><p>我们已经定义了 Point 类，现在 Point 是一种新数据类型，我们可以使用下面的代码声明一个变量，存储一个 Point 对象：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Point p;</span><br></pre></td></tr></table></figure>

<p>不过，声明一个存储 Point 对象的变量并不会创建这个对象。要想创建对象，必须使用<code>new</code> 运算符。这个关键字后面跟着对象所属的类（即对象的类型）和括号中可选的参数列表。这些参数会传入类的构造方法，初始化新对象的内部字段：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 创建一个Point对象，表示(2,-3.5) </span></span><br><span class="line"><span class="comment">// 声明一个变量p，存储这个新Point对象的引用 </span></span><br><span class="line">Point p = <span class="keyword">new</span> Point(<span class="number">2.0</span>, -<span class="number">3.5</span>); </span><br><span class="line"> </span><br><span class="line"><span class="comment">// 创建一些其他类型的对象 </span></span><br><span class="line"><span class="comment">// 一个Date对象，表示当前时间 </span></span><br><span class="line">Date d = <span class="keyword">new</span> Date(); </span><br><span class="line"><span class="comment">// 一个HashSet对象，保存一些对象 </span></span><br><span class="line">Set words = <span class="keyword">new</span> HashSet();</span><br></pre></td></tr></table></figure>

<p><code>new</code> 关键字是目前为止在 Java 中创建对象最常用的方式。还有一些其他方式也有必要提一下。首先，有些符合特定条件的类很重要，Java 为这些类定义了专用的字面量句法，用于创建这些类型的对象。其次，Java 支持动态加载机制，允许程序动态加载类和创建类的实例。最后，对象还可以通过反序列化创建。对象的状态可以保存或序列化到一个文件中，然后可以使用 <code>java.io.ObjectInputStream</code> 类重新创建这个对象。</p>
<h3 id="使用对象"><a href="#使用对象" class="headerlink" title="使用对象"></a>使用对象</h3><p>我们已经知道如何定义类，如何通过创建对象实例化类，现在要介绍使用对象的 Java 句法。前面说过，类定义了一些字段和方法。每个对象都有自己的字段副本，而且可以访问类中的方法。我们使用点号（<code>.</code>）访问对象的具名字段和方法。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Point p = <span class="keyword">new</span> Point(<span class="number">2</span>, <span class="number">3</span>);         <span class="comment">// 创建一个对象 </span></span><br><span class="line"><span class="keyword">double</span> x = p.x;                    <span class="comment">// 读取这个对象的一个字段 </span></span><br><span class="line">p.y = p.x * p.x;                   <span class="comment">// 设定一个字段的值 </span></span><br><span class="line"><span class="keyword">double</span> d = p.distanceFromOrigin(); <span class="comment">// 访问这个对象的一个方法</span></span><br></pre></td></tr></table></figure>

<p>这种句法在面向对象语言中很常见，Java 也不例外，因此会经常见到。特别注意一下 <code>p.distanceFromOrigin()</code>。这个表达式告诉 Java 编译器，查找一个名为<code>distanceFromOrigin()</code> 的方法（在 Point 类中定义），然后使用这个方法对 p 对象的字段进行计算。</p>
<h3 id="对象字面量"><a href="#对象字面量" class="headerlink" title="对象字面量"></a>对象字面量</h3><p>介绍基本类型时我们看到，每种基本类型都有字面量句法，可以直接在程序的代码中插入各种类型的值。Java 还为一些特殊的引用类型定义了字面量句法，介绍如下。</p>
<h4 id="字符串字面量"><a href="#字符串字面量" class="headerlink" title="字符串字面量"></a>字符串字面量</h4><p>String 类使用一串字符表示文本。因为程序经常需要通过文字和用户沟通，所以在任何编程语言中处理文本字符串的能力都十分重要。在 Java 中，字符串是对象，表示文本的数据类型是 String 类。现代 Java 程序使用的字符串数据通常比其他程序都多。</p>
<p>因为字符串是如此基本的数据类型，所以 Java 允许在程序中插入文本字面量，方法是把字符放在双引号（<code>&quot;</code>）中。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">String name = <span class="string">"David"</span>; </span><br><span class="line">System.out.println(<span class="string">"Hello, "</span> + name);</span><br></pre></td></tr></table></figure>

<blockquote>
<p>别把字符串字面量两侧的双引号和字符字面量两侧的单引号搞混了。</p>
</blockquote>
<p>字符串字面量可以包含字符字面量中能使用的任何一个转义序列。在双引号包围的字符串字面量中嵌入双引号时，转义序列特别有用。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">String story = <span class="string">"\t\"How can you stand it?\" he asked sarcastically.\n"</span>;</span><br></pre></td></tr></table></figure>

<p>字符串字面量中不能包含注释，而且只能有一行。Java 不支持把两行当成一行的任何接续字符。如果需要表示一串长文本，一行写不下，可以把这个文本拆成多个单独的字符串字面量，再使用 <code>+</code> 运算符把它们连接起来。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">String s = <span class="string">"This is a test of the "</span> +      <span class="comment">// 要这么写 </span></span><br><span class="line">           <span class="string">"emergency broadcast system"</span>;</span><br></pre></td></tr></table></figure>

<p>这种字面量连接在编译程序时，而不是运行时完成，所以无需担心性能会降低。</p>
<h4 id="类型字面量"><a href="#类型字面量" class="headerlink" title="类型字面量"></a>类型字面量</h4><p>第二种支持专用对象字面量句法的类型是 Class 类。Class 类的实例表示一种 Java 数据类型，而且包含所表示类型的元数据。若想在 Java 程序中使用 Class 对象字面量，要在数据类型的名称后面加上 .class。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Class&lt;?&gt; typeInt = <span class="keyword">int</span><span class="class">.<span class="keyword">class</span></span>; </span><br><span class="line">Class&lt;?&gt; typeIntArray = <span class="keyword">int</span>[]<span class="class">.<span class="keyword">class</span></span>; </span><br><span class="line">Class&lt;?&gt; typePoint = Point<span class="class">.<span class="keyword">class</span></span>;</span><br></pre></td></tr></table></figure>

<h4 id="null引用"><a href="#null引用" class="headerlink" title="null引用"></a><code>null</code>引用</h4><p><code>null</code> 关键字是一种特殊的字面量，引用不存在的值，或者不引用任何值。null 这个值是独一无二的，因为它是任何一种引用类型的成员。null 可以赋值给属于任何引用类型的变量。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">String s = <span class="keyword">null</span>; </span><br><span class="line">Point p = <span class="keyword">null</span>;</span><br></pre></td></tr></table></figure>

<h3 id="lambda表达式"><a href="#lambda表达式" class="headerlink" title="lambda表达式"></a>lambda表达式</h3><p>Java 8 引入了一个重要的新功能——lambda 表达式。这是十分常见的编程语言结构，在函数式编程语言（Functional Programming Language，例如 Lisp、Haskell 和 OCaml）中使用范围极广。lambda 表达式的功能和灵活性远非局限于函数式语言，在几乎所有的现代编程语言中都能看到它的身影。</p>
<blockquote>
<p>lambda 表达式其实就是没有名称的函数，在 Java 中可以把它当成一个值。Java 不允许脱离类的概念运行方法，所以 lambda 表达式是在某个类中定义的匿名方法（开发者可能不知道具体是哪个类）。</p>
</blockquote>
<p>lambda 表达式的句法如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">( paramlist ) -&gt; &#123; statements &#125;</span><br></pre></td></tr></table></figure>

<p>下面是一个十分传统的简单示例：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Runnable r = () -&gt; System.out.println(<span class="string">"Hello World"</span>);</span><br></pre></td></tr></table></figure>

<p>lambda 表达式当成值使用时，会根据要存储的变量类型，自动转换为相应的对象。自动转换和类型推导是 Java 实现 lambda 表达式的基础。但是，这要求正确地理解 Java 的整个类型系统。</p>
<p>下面是个稍微复杂的示例：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">ActionListener listener = (e) -&gt; &#123; </span><br><span class="line">  System.out.println(<span class="string">"Event fired at: "</span>+ e.getWhen()); </span><br><span class="line">  System.out.println(<span class="string">"Event command: "</span>+ e.getActionCommand()); </span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<h2 id="数组"><a href="#数组" class="headerlink" title="数组"></a>数组</h2><p>数组是一种特殊的对象，保存零个或多个基本类型或引用类型的值。这些值是数组的元素，是通过所在位置或索引引用的无名变量。数组的类型通过元素的类型表示，数组中的所有元素必须都属于这个类型。</p>
<p>数组元素的编号<strong>从零开始</strong>，有效的索引范围是零到元素数量减一。例如，索引为 1 的元素，是数组中的第二个元素。数组中的元素数量是数组的长度。数组的长度在创建时指定，从此就<strong>不能改变</strong>。</p>
<p>数组中元素的类型可以是任何有效的 Java 类型，包括数组类型。也就是说，Java 支持由数组组成的数组，实现多维数组。Java 不支持其他语言中的矩阵式多维数组。</p>
<h3 id="数组的类型"><a href="#数组的类型" class="headerlink" title="数组的类型"></a>数组的类型</h3><p>数组的类型和类一样，也是引用类型。数组的实例和类的实例一样，也是对象。和类不同的是，数组的类型不用定义，只需在元素类型后面加上一对中括号即可。例如，下述代码声明了三种不同类型的数组：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">byte</span> b;                        <span class="comment">// byte是基本类型 </span></span><br><span class="line"><span class="keyword">byte</span>[] arrayOfBytes;           <span class="comment">// byte[]是由byte类型的值组成的数组 </span></span><br><span class="line"><span class="keyword">byte</span>[][] arrayOfArrayOfBytes;  <span class="comment">// byte[][]是由byte[]类型的值组成的数组 </span></span><br><span class="line">String[] points;               <span class="comment">// String[]是由字符串组成的数组</span></span><br></pre></td></tr></table></figure>

<p>数组的长度不是数组类型的一部分。例如，声明一个方法，并且期望传入恰好由四个 int 类型的值组成的数组，是不可能的。如果方法的参数类型是 <code>int[]</code>，调用时传入的数组可以包含任意个元素（包括零个）。</p>
<p>数组类型不是类，但数组实例是对象。这意味着，数组从 <code>java.lang.Object</code> 类继承了方法。数组实现了 <code>Cloneable</code> 接口，而且覆盖了 <code>clone()</code> 方法，确保数组始终能被复制，而且 <code>clone()</code> 方法从不抛出 <code>CloneNotSupportedException</code> 异常。数组还实现了 <code>Serializable</code> 接口，所以只要数组中元素的类型能被序列化，数组就能被序列化。而且，所有数组都有一个名为 <code>length</code> 的字段，这个字段的修饰符是 <code>public final int</code>，表示数组中元素的数量。</p>
<hr>
<p>1、数组类型放大转换</p>
<p>因为数组扩展自 <code>Object</code> 类，而且实现了 <code>Cloneable</code> 和 <code>Serializable</code> 接口，所以任何数组类型都能放大转换成这三种类型中的任何一种。而且，特定的数组类型还能放大转换成其他数组类型。如果数组中的元素类型是引用类型 T，而且 T 能指定给类型 S，那么数组类型<code>T[]</code> 就能指定给数组类型 <code>S[]</code>。注意，基本类型的数组不能放大转换。例如，下述代码展示了合法的数组放大转换：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">String[] arrayOfStrings;      <span class="comment">// 创建字符串数组 </span></span><br><span class="line"><span class="keyword">int</span>[][] arrayOfArraysOfInt;   <span class="comment">// 创建int二维数组 </span></span><br><span class="line"><span class="comment">// String可以指定给Object， </span></span><br><span class="line"><span class="comment">// 因此String[]可以指定给Object[] </span></span><br><span class="line">Object[] oa = arrayOfStrings; </span><br><span class="line"><span class="comment">// String实现了Comparable接口 </span></span><br><span class="line"><span class="comment">// 因此String[]可以视作Comparable[] </span></span><br><span class="line">Comparable[] ca = arrayOfStrings; </span><br><span class="line"><span class="comment">// int[]是Object类的对象，因此int[][]可以指定给Object[] </span></span><br><span class="line">Object[] oa2 = arrayOfArraysOfInt; </span><br><span class="line"><span class="comment">// 所有数组都是可以复制和序列化的对象 </span></span><br><span class="line">Object o = arrayOfStrings; </span><br><span class="line">Cloneable c = arrayOfArraysOfInt; </span><br><span class="line">Serializable s = arrayOfArraysOfInt[<span class="number">0</span>];</span><br></pre></td></tr></table></figure>

<p>因为数组类型可以放大转换成另一种数组类型，所以编译时和运行时数组的类型并不总是一样。</p>
<blockquote>
<p>这种放大转换叫作“数组协变”（array covariance）。现代标准认为这是历史遗留的不合理功能，因为编译时和运行时得出的类型不一致。</p>
</blockquote>
<p>把引用类型的值存储在数组元素中之前，编译器通常必须插入运行时检查，确保运行时这个值的类型和数组元素的类型匹配。如果运行时检查失败，会抛出 <code>ArrayStoreException</code>异常。</p>
<p>2、与C语言兼容的句法</p>
<p>如前所示，指定数组类型的方法是在元素类型后加上一对中括号。为了兼容 C 和 C++，Java 还支持一种声明变量的句法：中括号放在变量名后面，元素类型后面可以放也可以不放中括号。这种句法可用于局部变量，字段和方法的参数。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 这行代码声明类型为int，int[]和int[][]的局部变量 </span></span><br><span class="line"><span class="keyword">int</span> justOne, arrayOfThem[], arrayOfArrays[][]; </span><br><span class="line"></span><br><span class="line"><span class="comment">// 这三行代码声明的字段属于同一种数组类型 </span></span><br><span class="line"><span class="keyword">public</span> String[][] aas1;   <span class="comment">// 推荐使用的Java句法 </span></span><br><span class="line"><span class="keyword">public</span> String aas2[][];   <span class="comment">// C语言的句法 </span></span><br><span class="line"><span class="keyword">public</span> String[] aas3[];   <span class="comment">// 令人困惑的混用句法 </span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 这个方法签名包含两个类型相同的参数 </span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">double</span> <span class="title">dotProduct</span><span class="params">(<span class="keyword">double</span>[] x, <span class="keyword">double</span> y[])</span> </span>&#123; ... &#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>这种兼容句法极其少见，不要使用。</p>
</blockquote>
<h3 id="创建和初始化数组"><a href="#创建和初始化数组" class="headerlink" title="创建和初始化数组"></a>创建和初始化数组</h3><p>在 Java 中，使用 new 关键字创建数组，就像创建对象一样。数组类型没有构造方法，但创建数组时要指定长度，在中括号里使用非负整数指定所需的数组大小：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 创建一个能保存1024个byte类型数据的新数组 </span></span><br><span class="line"><span class="keyword">byte</span>[] buffer = <span class="keyword">new</span> <span class="keyword">byte</span>[<span class="number">1024</span>]; </span><br><span class="line"><span class="comment">// 创建一个能保存50个字符串引用的数组 </span></span><br><span class="line">String[] lines = <span class="keyword">new</span> String[<span class="number">50</span>];</span><br></pre></td></tr></table></figure>

<p>使用这种句法创建的数组，每个元素都会自动初始化，初始值和类中的字段默认值相同：</p>
<ul>
<li>boolean 类型元素的初始值是 false；</li>
<li>char 类型元素的初始值是 \u0000；</li>
<li>整数元素的初始值是 0；</li>
<li>浮点数元素的初始值是 0.0；</li>
<li>引用类型元素的初始值是 null。</li>
</ul>
<p>创建数组的表达式也能用来创建和初始化多维数组。这种句法稍微复杂一些。</p>
<p><strong>数组初始化程序</strong></p>
<p>若想在一个表达式中创建数组并初始化其中的元素，不要指定数组的长度，在方括号后面跟着一对花括号，在花括号里写入一些逗号分隔的表达式。当然了，每个表达式的返回值类型必须能指定给数组元素的类型。创建的数组长度和表达式的数量相等。这组表达式的最后一个后面可以加上逗号，但没必要这么做。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">String[] greetings = <span class="keyword">new</span> String[] &#123; <span class="string">"Hello"</span>, <span class="string">"Hi"</span>, <span class="string">"Howdy"</span> &#125;; </span><br><span class="line"><span class="keyword">int</span>[] smallPrimes = <span class="keyword">new</span> <span class="keyword">int</span>[] &#123; <span class="number">2</span>, <span class="number">3</span>, <span class="number">5</span>, <span class="number">7</span>, <span class="number">11</span>, <span class="number">13</span>, <span class="number">17</span>, <span class="number">19</span>, &#125;;</span><br></pre></td></tr></table></figure>

<p>注意，这种句法无需把数组赋值给变量就能创建、初始化和使用数组。某种意义上，这种创建数组的表达式相当于匿名数组字面量。下面是几个示例：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 调用一个方法，传入一个包含两个字符串的匿名数组字面量 </span></span><br><span class="line">String response = askQuestion(<span class="string">"Do you want to quit?"</span>, </span><br><span class="line">                               <span class="keyword">new</span> String[] &#123;<span class="string">"Yes"</span>, <span class="string">"No"</span>&#125;); </span><br><span class="line"><span class="comment">// 调用另一个方法，传入匿名对象组成的匿名数组 </span></span><br><span class="line"><span class="keyword">double</span> d = computeAreaOfTriangle(<span class="keyword">new</span> Point[] &#123; <span class="keyword">new</span> Point(<span class="number">1</span>,<span class="number">2</span>), </span><br><span class="line">                                               <span class="keyword">new</span> Point(<span class="number">3</span>,<span class="number">4</span>), </span><br><span class="line">                                               <span class="keyword">new</span> Point(<span class="number">3</span>,<span class="number">2</span>) &#125;);</span><br></pre></td></tr></table></figure>

<p>如果数组初始化程序是变量声明的一部分，可以省略 new 关键字和元素类型，在花括号里列出所需的元素：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">String[] greetings = &#123; <span class="string">"Hello"</span>, <span class="string">"Hi"</span>, <span class="string">"Howdy"</span> &#125;; </span><br><span class="line"><span class="keyword">int</span>[] powersOfTwo = &#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">4</span>, <span class="number">8</span>, <span class="number">16</span>, <span class="number">32</span>, <span class="number">64</span>, <span class="number">128</span>&#125;;</span><br></pre></td></tr></table></figure>

<p>数组字面量在程序运行时，而不是程序编译时，创建和初始化。例如下述数组字面量：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span>[] perfectNumbers = &#123;<span class="number">6</span>, <span class="number">28</span>&#125;;</span><br></pre></td></tr></table></figure>

<p>编译得到的 Java 字节码和下面的代码相同：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span>[] perfectNumbers = <span class="keyword">new</span> <span class="keyword">int</span>[<span class="number">2</span>]; </span><br><span class="line">perfectNumbers[<span class="number">0</span>] = <span class="number">6</span>; </span><br><span class="line">perfectNumbers[<span class="number">1</span>] = <span class="number">28</span>;</span><br></pre></td></tr></table></figure>


<p>Java 在运行时初始化数组有个重要的推论：数组初始化程序中的表达式可能会在运行时计算，而且不一定非要使用编译时常量。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Point[] points = &#123; circle1.getCenterPoint(), circle2.getCenterPoint() &#125;;</span><br></pre></td></tr></table></figure>

<h3 id="使用数组"><a href="#使用数组" class="headerlink" title="使用数组"></a>使用数组</h3><p>创建数组后就可以开始使用了。包括访问元素的基本方法，以及常见的数组用法，例如迭代数组中的元素，复制数组或数组的一部分。</p>
<h4 id="访问数组中的元素"><a href="#访问数组中的元素" class="headerlink" title="访问数组中的元素"></a>访问数组中的元素</h4><p>数组中的元素是变量。如果元素出现在表达式中，其计算结果是这个元素中保存的值。如果元素出现在赋值运算符的左边，会把一个新值保存到这个元素中。不过，元素和普通的变量不同，它没有名字，只有编号。数组中的元素使用方括号访问。假如 a 是一个表达式，其计算结果为一个数组引用，那么可以使用 <code>a[i]</code> 索引数组，并引用某个元素。其中，i 是整数字面量或计算结果为 int 类型值的表达式。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 创建一个由两个字符串组成的数组 </span></span><br><span class="line">String[] responses = <span class="keyword">new</span> String[<span class="number">2</span>];</span><br><span class="line">responses[<span class="number">0</span>] = <span class="string">"Yes"</span>;  <span class="comment">// 设定数组的第一个元素 </span></span><br><span class="line">responses[<span class="number">1</span>] = <span class="string">"No"</span>;   <span class="comment">// 设定数组的第二个元素 </span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 读取这个数组中的元素 </span></span><br><span class="line">System.out.println(question + <span class="string">" ("</span> + responses[<span class="number">0</span>] + <span class="string">"/"</span> + </span><br><span class="line">                   responses[<span class="number">1</span>] + <span class="string">" ): "</span>); </span><br><span class="line"> </span><br><span class="line"><span class="comment">// 数组引用和数组索引都可以是复杂的表达式 </span></span><br><span class="line"><span class="keyword">double</span> datum = data.getMatrix()[data.row() * data.numColumns() + </span><br><span class="line">                   data.column()];</span><br></pre></td></tr></table></figure>

<p>数组的索引表达式必须是 int 类型，或能放大转换成 int 的类型：byte、short，甚至是char。数组的索引显然不能是 boolean、float 或 double 类型。还记得吗，数组的 length字段是 int 类型，所以数组中的元素数量不能超过 <code>Integer.MAX_VALUE</code>。如果使用 long 类型的表达式索引数组，即便运行时表达式的返回值在 int 类型的取值范围内，也会导致编译出错。</p>
<h4 id="数组的边界"><a href="#数组的边界" class="headerlink" title="数组的边界"></a>数组的边界</h4><p>还记得吗？数组 a 的第一个元素是 <code>a[0]</code>，第二个元素是 <code>a[1]</code>，最后一个元素是 <code>a[a.length-1]</code>。</p>
<p>使用数组时常见的错误是索引太小（负数）或太大（大于或等于数组的长度）。在 C 或C++ 等语言中，如果访问起始索引之前或结尾索引之后的元素，会导致无法预料的行为，而且在不同的调用和不同的平台中有所不同。这种问题不一定会被捕获，如果没捕获，可能过一段时间才会发现。因为在 Java 中容易编写错误的索引代码，所以运行时每次访问数组都会做检查，确保得到能预料的结果。如果数组的索引太小或太大，Java 会立即抛出<code>ArrayIndexOutOfBoundsException</code> 异常。</p>
<h4 id="迭代数组"><a href="#迭代数组" class="headerlink" title="迭代数组"></a>迭代数组</h4><p>为了在数组上执行某种操作，经常要编写循环，迭代数组中的每个元素。这种操作通常使用 for 循环完成。例如，下述代码计算整数数组中的元素之和：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span>[] primes = &#123; <span class="number">2</span>, <span class="number">3</span>, <span class="number">5</span>, <span class="number">7</span>, <span class="number">11</span>, <span class="number">13</span>, <span class="number">17</span>, <span class="number">19</span>, <span class="number">23</span> &#125;; </span><br><span class="line"><span class="keyword">int</span> sumOfPrimes = <span class="number">0</span>; </span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; primes.length; i++) </span><br><span class="line">    sumOfPrimes += primes[i];</span><br></pre></td></tr></table></figure>

<p>这种 for 循环结构很有特色，会经常见到。Java 还支持遍历句法，前面已经介绍过。上述求和代码可以改写成下述简洁的代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span>(<span class="keyword">int</span> p : primes) sumOfPrimes += p;</span><br></pre></td></tr></table></figure>

<h4 id="复制数组"><a href="#复制数组" class="headerlink" title="复制数组"></a>复制数组</h4><p>所有数组类型都实现了 <code>Cloneable</code> 接口，任何数组都能调用 <code>clone()</code> 方法复制自己。注意，返回值必须校正成适当的数组类型。不过，在数组上调用 <code>clone()</code> 方法不会抛出<code>CloneNotSupportedException</code> 异常：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span>[] data = &#123; <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span> &#125;; </span><br><span class="line"><span class="keyword">int</span>[] copy = (<span class="keyword">int</span>[]) data.clone();</span><br></pre></td></tr></table></figure>

<p><code>clone()</code> 方法执行的是浅复制。如果数组的元素是引用类型，那么只复制引用，而<strong>不复制引用的对象</strong>。因为这种复制是浅复制，所以任何数组都能被复制，就算元素类型没有实现<code>Cloneable</code> 接口也行。</p>
<p>不过，有时只想把一个现有数组中的元素复制到另一个现有数组中。<code>System.arraycopy()</code>方法的目的就是高效完成这种操作。你可以假定 Java 虚拟机实现会在底层硬件中使用高速块复制操作执行这个方法。</p>
<p><code>arraycopy()</code> 方法的作用简单明了，但使用起来有些难度，因为要记住五个参数。</p>
<ul>
<li>第一个参数是想从中复制元素的源数组；</li>
<li>第二个参数是源数组中起始元素的索引；</li>
<li>第三个参数是目标数组；</li>
<li>第四个参数是目标索引；</li>
<li>第五个参数是要复制的元素数量。</li>
</ul>
<p>就算重叠复制同一个数组，<code>arraycopy()</code> 方法也能正确运行。例如，把数组 a 中索引为 0 的  元素删除后，想把索引为 1 到 n 的元素向左移，把索引变成 0 到 n-1，可以这么做：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">System.arraycopy(a, <span class="number">1</span>, a, <span class="number">0</span>, n);</span><br></pre></td></tr></table></figure>

<h4 id="数组的实用方法"><a href="#数组的实用方法" class="headerlink" title="数组的实用方法"></a>数组的实用方法</h4><p><code>java.util.Arrays</code> 类中包含很多处理数组的静态实用方法。这些方法中大多数都高度重载，有针对各种基本类型数组的版本，也有针对对象数组的版本。排序和搜索数组时，<code>sort()</code>和 <code>binarySearch()</code> 方法特别有用。<code>equals()</code> 方法用于比较两个数组的内容。如果想把数组的内容转换成一个字符串，例如用于调试或记录日志，<code>Arrays.toString()</code> 方法很有用。Arrays 类中还包含能正确处理多维数组的方法，例如 <code>deepEquals()</code>、<code>deepHashCode()</code> 和<code>deepToString()</code>。</p>
<h3 id="多维数组"><a href="#多维数组" class="headerlink" title="多维数组"></a>多维数组</h3><p>前面已经见过，数组类型的写法是在元素类型后面加一对方括号。<code>char</code> 类型元素组成的数组是 <code>char[]</code> 类型，由 <code>char[]</code> 类型元素组成的数组是 <code>char[][]</code>类型。如果数组的元素也是数组，我们说这个数组是多维数组。要想使用多维数组，需要了解一些其他细节。假如想使用多维数组表示乘法表：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">int[][] products;     &#x2F;&#x2F; 乘法表</span><br></pre></td></tr></table></figure>

<p>每对方括号表示一个维度，所以这是个二维数组。若想访问这个二维数组中的某个 <code>int</code>元素，必须指定两个索引值，一个维度一个。假设这个数组确实被初始化成一个乘法表，那么元素中存储的 int 值就是两个索引的乘积。也就是说，<code>products[2][4]</code> 的值是 8，<code>products[3][7]</code> 的值是 21。创建多维数组要使用 new 关键字，而且要指定每个维度中数组的大小。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span>[][] products = <span class="keyword">new</span> <span class="keyword">int</span>[<span class="number">10</span>][<span class="number">10</span>];</span><br></pre></td></tr></table></figure>

<p>在某些语言中，会把这样的数组创建成包含 100 个 int 值的数组，但 Java 不会这样处理。这行代码会做三件事。</p>
<ul>
<li>声明一个名为 products 的变量，保存一个由 <code>int[]</code> 类型数组组成的数组。</li>
<li>创建一个有 10 个元素的数组，保存 10 个 <code>int[]</code> 类型的数组。</li>
<li>再创建 10 个数组，每个都由 10 个 <code>int</code> 类型的元素组成。然后把这 10 个新数组指定为前一步创建的数组的元素。这 10 个新数组中的每一个 int 类型元素的默认值都是 0。</li>
</ul>
<p>换种方式说，前面的单行代码等效于下述代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span>[][] products = <span class="keyword">new</span> <span class="keyword">int</span>[<span class="number">10</span>][];  <span class="comment">// 保存10个int[]类型值的数组 </span></span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">10</span>; i++)        <span class="comment">// 循环10次…… </span></span><br><span class="line">    products[i] = <span class="keyword">new</span> <span class="keyword">int</span>[<span class="number">10</span>];     <span class="comment">// ……创建10个数组</span></span><br></pre></td></tr></table></figure>

<p>new 关键字会自动执行这些额外的初始化操作。超过两个维度的数组也是一样：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">float</span>[][][] globalTemperatureData = <span class="keyword">new</span> <span class="keyword">float</span>[<span class="number">360</span>][<span class="number">180</span>][<span class="number">100</span>];</span><br></pre></td></tr></table></figure>

<p>使用 new 关键字创建多维数组时，无需指定所有维度的大小，只要为最左边的几个维度指定大小就行。例如，下面两行代码都是合法的：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">float</span>[][][] globalTemperatureData = <span class="keyword">new</span> <span class="keyword">float</span>[<span class="number">360</span>][][]; </span><br><span class="line"><span class="keyword">float</span>[][][] globalTemperatureData = <span class="keyword">new</span> <span class="keyword">float</span>[<span class="number">360</span>][<span class="number">180</span>][];</span><br></pre></td></tr></table></figure>

<p>第一行代码创建一个一维数组，元素是 <code>float[][]</code> 类型。第二行代码创建一个二维数组，元素是 <code>float[]</code> 类型。不过，如果只为数组的部分维度指定大小，这些维度必须位于最左边。下述代码是不合法的：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">float</span>[][][] globalTemperatureData = <span class="keyword">new</span> <span class="keyword">float</span>[<span class="number">360</span>][][<span class="number">100</span>]; <span class="comment">// 错误！ </span></span><br><span class="line"><span class="keyword">float</span>[][][] globalTemperatureData = <span class="keyword">new</span> <span class="keyword">float</span>[][<span class="number">180</span>][<span class="number">100</span>]; <span class="comment">// 错误！</span></span><br></pre></td></tr></table></figure>

<p>和一维数组一样，多维数组也能使用数组初始化程序初始化，使用嵌套的花括号把数组嵌套在数组中即可。例如，可以像下面这样声明、创建并初始化一个 5×5 乘法表：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span>[][] products = &#123; &#123;<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>&#125;, </span><br><span class="line">                     &#123;<span class="number">0</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>&#125;, </span><br><span class="line">                     &#123;<span class="number">0</span>, <span class="number">2</span>, <span class="number">4</span>, <span class="number">6</span>, <span class="number">8</span>&#125;, </span><br><span class="line">                     &#123;<span class="number">0</span>, <span class="number">3</span>, <span class="number">6</span>, <span class="number">9</span>, <span class="number">12</span>&#125;, </span><br><span class="line">                     &#123;<span class="number">0</span>, <span class="number">4</span>, <span class="number">8</span>, <span class="number">12</span>, <span class="number">16</span>&#125; &#125;;</span><br></pre></td></tr></table></figure>

<p>如果不想声明变量就使用多维数组，可以使用匿名初始化程序句法：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">boolean</span> response = bilingualQuestion(question, <span class="keyword">new</span> String[][] &#123; </span><br><span class="line">                                                   &#123; <span class="string">"Yes"</span>, <span class="string">"No"</span> &#125;, </span><br><span class="line">                                                   &#123; <span class="string">"Oui"</span>, <span class="string">"Non"</span> &#125;&#125;);</span><br></pre></td></tr></table></figure>

<p>使用 new 关键字创建多维数组时，往往最好只使用矩形数组，即每个维度的数组大小相同。</p>
<h3 id="数组存储的弊端"><a href="#数组存储的弊端" class="headerlink" title="数组存储的弊端"></a>数组存储的弊端</h3><ul>
<li>一旦初始化以后，其长度就不可修改。</li>
<li>数组中提供的方法非常限，对于添加、删除、插入数据等操作，非常不便，同时数率不高</li>
<li>获取数组中实际元素的个数的需求，数组没有现成的属性或方法可用</li>
<li>数组存储数据的特点：序字、可重复。对于无序、不可重复的需求，不能满足。</li>
</ul>
<h2 id="引用类型"><a href="#引用类型" class="headerlink" title="引用类型"></a>引用类型</h2><p>至此，我们已经介绍了数组、类和对象，接下来可以介绍更一般的引用类型了。类和数组是 Java 五种引用类型中的两种。本节不涉及任何引用类型的具体句法，而是说明引用类型的一般行为，还会说明引用类型和基本类型的区别。本节使用术语“对象”指代引用类型（包括数组）的值或实例。</p>
<h3 id="引用类型与基本类型比较"><a href="#引用类型与基本类型比较" class="headerlink" title="引用类型与基本类型比较"></a>引用类型与基本类型比较</h3><p>引用类型和对象与基本类型和基本值有本质的区别。</p>
<ul>
<li>八种基本类型由 Java 语言定义，程序员不能定义新基本类型。引用类型由用户定义，因此有无限多个。例如，程序可以定义一个名为 Point 的类，然后使用这个新定义类型的对象存储和处理笛卡儿坐标系中的 (x, y) 点。</li>
<li>基本类型表示单个值。引用类型是聚合类型（aggregate type），可以保存零个或多个基本值或对象。例如，我们假设的 <code>Point</code> 类可能存储了两个 <code>double</code> 类型的值，表示点的 x 和 y 坐标。<code>char[]</code> 和 <code>Point[]</code> 数组类型是聚合类型，因为它们保存一些 <code>char</code> 类型的基本值或 <code>Point</code> 对象。</li>
<li>基本类型需要一到八个字节的内存空间。把基本值存储到变量中，或者传入方法时，计算机会复制表示这个值的字节。而对象基本上需要更多的内存。创建对象时会在堆（heap）中动态分配内存，存储这个对象；如果不再需要使用这个对象了，存储它的内存会被自动垃圾回收。</li>
</ul>
<blockquote>
<p>把对象赋值给变量或传入方法时，不会复制表示这个对象的内存，而是把这个内存的引用存储在变量中或传入方法。</p>
</blockquote>
<p>在 Java 中，引用完全不透明，引用的表示方式由 Java 运行时的实现细节决定。如果你是C 程序员的话，完全可以把引用看作指针或内存地址。不过要记住，Java 程序无法使用任何方式处理引用。与 C 和 C++ 中的指针不同的是，引用不能转换成整数，也不能把整数转换成引用，而且不能递增或递减。C 和 C++ 程序员还要注意，Java 不支持求地址运算符 <code>&amp;</code>，也不支持解除引用运算符 <code>*</code> 和 <code>-&gt;</code>。</p>
<h3 id="处理对象和引用副本"><a href="#处理对象和引用副本" class="headerlink" title="处理对象和引用副本"></a>处理对象和引用副本</h3><p>下述代码处理 int 类型基本值：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> x = <span class="number">42</span>; </span><br><span class="line"><span class="keyword">int</span> y = x;</span><br></pre></td></tr></table></figure>

<p>执行这两行代码后，变量 y 中保存了变量 x 中所存值的一个副本。在 Java 虚拟机内部，这个 32 位整数 42 有两个独立的副本。<br>现在，想象一下把这段代码中的基本类型换成引用类型后再运行会发生什么：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Point p = <span class="keyword">new</span> Point(<span class="number">1.0</span>, <span class="number">2.0</span>); </span><br><span class="line">Point q = p;</span><br></pre></td></tr></table></figure>

<p>运行这段代码后，变量 q 中保存了一份变量 p 中所存引用的一个副本。在虚拟机中，仍然只有一个 Point 对象的副本，但是这个对象的引用有两个副本——这一点有重要的含义。假设上面两行代码的后面是下述代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">System.out.println(p.x);  <span class="comment">// 打印p的x坐标：1.0 </span></span><br><span class="line">q.x = <span class="number">13.0</span>;               <span class="comment">// 现在，修改q的x坐标 </span></span><br><span class="line">System.out.println(p.x);  <span class="comment">// 再次打印p.x，这次得到的值是13.0</span></span><br></pre></td></tr></table></figure>

<p>因为变量 p 和 q 保存的引用指向同一个对象，所以两个变量都可以用来修改这个对象，而且一个变量中的改动在另一个变量中可见。数组也是一种对象，所以对数组来说也会发生同样的事，如下面的代码所示：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// greet保存一个数组的引用 </span></span><br><span class="line"><span class="keyword">char</span>[] greet = &#123; <span class="string">'h'</span>,<span class="string">'e'</span>,<span class="string">'l'</span>,<span class="string">'l'</span>,<span class="string">'o'</span> &#125;; </span><br><span class="line"><span class="keyword">char</span>[] cuss = greet;             <span class="comment">// cuss保存的是同一个数组的引用 </span></span><br><span class="line">cuss[<span class="number">4</span>] = <span class="string">'!'</span>;                   <span class="comment">// 使用引用修改一个元素 </span></span><br><span class="line">System.out.println(greet);       <span class="comment">// 打印“hell!”</span></span><br></pre></td></tr></table></figure>

<p>把基本类型和引用类型的参数传入方法时也有类似的区别。假如有下面的方法：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">changePrimitive</span><span class="params">(<span class="keyword">int</span> x)</span> </span>&#123; </span><br><span class="line">    <span class="keyword">while</span>(x &gt; <span class="number">0</span>) &#123; </span><br><span class="line">        System.out.println(x--); </span><br><span class="line">    &#125; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>调用这个方法时，会把实参的副本传给形参 x。在这个方法的代码中，x 是循环计数器，向零递减。因为 x 是基本类型，所以这个方法有这个值的私有副本——这是完全合理的做法。</p>
<p>可是，如果把这个方法的参数改为引用类型，会发生什么呢？</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">changeReference</span><span class="params">(Point p)</span> </span>&#123; </span><br><span class="line">    <span class="keyword">while</span>(p.x &gt; <span class="number">0</span>) &#123; </span><br><span class="line">        System.out.println(p.x--); </span><br><span class="line">    &#125; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>调用这个方法时，传入的是一个 Point 对象引用的私有副本，然后使用这个引用修改对应的 Point 对象。例如，有下述代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Point q = <span class="keyword">new</span> Point(<span class="number">3.0</span>, <span class="number">4.5</span>); <span class="comment">// 一个x坐标为3的点 </span></span><br><span class="line">changeReference(q);            <span class="comment">// 打印3，2，1，而且修改了这个Point对象 </span></span><br><span class="line">System.out.println(q.x);       <span class="comment">// 现在，q的x坐标是0！</span></span><br></pre></td></tr></table></figure>

<p>调用 <code>changeReference()</code> 方法时，传入的是变量 q 中所存引用的副本。现在，变量 q 和方法的形参 p 保存的引用指向同一个对象。这个方法可以使用它的引用修改对象的内容。但是要注意，这个方法不能修改变量 q 的内容。也就是说，这个方法可以随意修改引用的 Point 对象，但不能改变变量 q 引用这个对象这一事实。</p>
<h3 id="比较对象"><a href="#比较对象" class="headerlink" title="比较对象"></a>比较对象</h3><p>我们已经介绍了基本类型和引用类型在赋值给变量、传入方法和复制时的显著区别。这两种类型在相等性比较时也有区别。相等运算符（<code>==</code>）比较基本值时，只测试两个值是否一样（即每一位的值都完全相同）。而 <code>==</code> 比较引用类型时，比较的是引用而不是真正的对象。也就是说，<code>==</code> 测试两个引用是否指向同一个对象，而不测试两个对象的内容是否相同。例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">String letter = <span class="string">"o"</span>; </span><br><span class="line">String s = <span class="string">"hello"</span>;              <span class="comment">// 这两个String对象 </span></span><br><span class="line">String t = <span class="string">"hell"</span> + letter;      <span class="comment">// 保存的文本完全一样 </span></span><br><span class="line"><span class="keyword">if</span> (s == t) System.out.println(<span class="string">"equal"</span>); <span class="comment">// 但是，二者并不相等！ </span></span><br><span class="line"> </span><br><span class="line"><span class="keyword">byte</span>[] a = &#123; <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span> &#125;; </span><br><span class="line"><span class="comment">// 内容一样的副本 </span></span><br><span class="line"><span class="keyword">byte</span>[] b = (<span class="keyword">byte</span>[]) a.clone(); </span><br><span class="line"><span class="keyword">if</span> (a == b) System.out.println(<span class="string">"equal"</span>); <span class="comment">// 但是，二者并不相等！</span></span><br></pre></td></tr></table></figure>

<p>对引用类型来说，有两种相等：引用相等和对象相等。一定要把这两种相等区分开。其中一种方式是，使用“相同”（identical）表示引用相等，使用“相等”（equal）表示对象的内容一样。若想测试两个不同的对象是否相等，可以在一个对象上调用 <code>equals()</code> 方法，然后把另一个对象传入这个方法：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">String letter = <span class="string">"o"</span>; </span><br><span class="line">String s = <span class="string">"hello"</span>;              <span class="comment">// 这两个String对象 </span></span><br><span class="line">String t = <span class="string">"hell"</span> + letter;      <span class="comment">// 保存的文本完全一样 </span></span><br><span class="line"><span class="keyword">if</span> (s.equals(t)) &#123;               <span class="comment">// equals()方法 </span></span><br><span class="line">    System.out.println(<span class="string">"equal"</span>); <span class="comment">// 证实了这一点 </span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>所有对象都（从 Object 类）继承了 <code>equals()</code> 方法，但是默认的实现方式是使用 <code>==</code> 测试引用是否相同，而不测试内容是否相等。想比较对象是否相等的类可以自定义 <code>equals()</code> 方法。Point 类没自定义，但 String 类自定义了，如前面的例子所示。可以在数组上调用 <code>equals()</code>方法，但作用和使用 <code>==</code> 运算符一样，因为数组始终继承默认的 <code>equals()</code> 方法，比较引用而不是数组的内容。比较数组是否相等可以使用 <code>java.util.Arrays.equals()</code> 实用方法。</p>
<h3 id="装包和拆包转换"><a href="#装包和拆包转换" class="headerlink" title="装包和拆包转换"></a>装包和拆包转换</h3><p>基本类型和引用类型的表现完全不同。有时需要把基本值当成对象，为此，Java 平台为每一种基本类型都提供了包装类。Boolean、Byte、Short、Character、Integer、Long、Float和 Double 是不可变的最终类，每个实例只保存一个基本值。包装类一般在把基本值存储在集合中时使用，例如 <code>java.util.List</code>：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 创建一个List集合 </span></span><br><span class="line">List numbers = <span class="keyword">new</span> ArrayList(); </span><br><span class="line"><span class="comment">// 存储一个包装类表示的基本值 </span></span><br><span class="line">numbers.add(<span class="keyword">new</span> Integer(-<span class="number">1</span>)); </span><br><span class="line"><span class="comment">// 取出这个基本值 </span></span><br><span class="line"><span class="keyword">int</span> i = ((Integer)numbers.get(<span class="number">0</span>)).intValue();</span><br></pre></td></tr></table></figure>

<p>Java 支持装包和拆包类型转换。装包转换<strong>把一个基本值转换成对应的包装对象</strong>，而拆包转换的作用相反。虽然可以通过校正显式指定装包和拆包转换，但没必要这么做，因为把值赋值给变量或传入方法时会自动执行这种转换。此外，如果把包装对象传给需要基本值的Java 运算符或语句，也会自动执行拆包转换。因为 Java 能自动执行装包和拆包转换，所以这种语言特性一般叫作自动装包（autoboxing）。</p>
<p>下面是一些自动装包和拆包转换的示例：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Integer i = <span class="number">0</span>;   <span class="comment">// 把int类型字面量0装包到Integer对象中 </span></span><br><span class="line">Number n = <span class="number">0.0f</span>; <span class="comment">// 把float类型字面量装包到Float对象中，然后放大转换成Number类型 </span></span><br><span class="line">Integer i = <span class="number">1</span>;   <span class="comment">// 这是装包转换 </span></span><br><span class="line"><span class="keyword">int</span> j = i;       <span class="comment">// i在这里拆包 </span></span><br><span class="line">i++;             <span class="comment">// 拆包i，递增，再装包 </span></span><br><span class="line">Integer k = i+<span class="number">2</span>; <span class="comment">// 拆包i，再装包两数之和 </span></span><br><span class="line">i = <span class="keyword">null</span>; </span><br><span class="line">j = i;           <span class="comment">// 这次拆包抛出NullPointerException异常</span></span><br></pre></td></tr></table></figure>

<p>自动装包也把集合处理变得更简单了。下面这个示例，使用 Java 的泛型限制列表和其他集合中能存储什么类型的值：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">List&lt;Integer&gt; numbers = <span class="keyword">new</span> ArrayList&lt;&gt;(); <span class="comment">// 创建一个由整数组成的列表 </span></span><br><span class="line">numbers.add(-<span class="number">1</span>);                           <span class="comment">// 把int类型的值装包到Integer对象中 </span></span><br><span class="line"><span class="keyword">int</span> i = numbers.get(<span class="number">0</span>);                    <span class="comment">// 把Integer对象拆包成int类型</span></span><br></pre></td></tr></table></figure>

<h2 id="包和Java命名空间"><a href="#包和Java命名空间" class="headerlink" title="包和Java命名空间"></a>包和Java命名空间</h2><p>包由一些具名的类、接口和其他引用类型组成，目的是把相关的类组织在一起，并为这些类定义命名空间。</p>
<p>Java 平台的核心类放在一些名称以 java 开头的包中。例如，Java 语言最基本的类在 <code>java.lang</code> 包中，各种实用类在 <code>java.util</code> 包中，输入输出类在 <code>java.io</code> 包中，网络类在 <code>java.net</code> 包中。有些包还包含子包，例如 <code>java.lang.reflect</code> 和 <code>java.util.regex</code>。甲骨文标准化的 Java 平台扩展一般在名称以 javax 开头的包中。有些扩展，例如 <code>javax.swing</code> 及其各种子包，后来集成到了核心平台中。最后，Java 平台还包含几个被认可的标准，这些包以标准制定方命名，例如 <code>org.w3c</code> 和 <code>org.omg</code>。</p>
<p>每个类都有两个名称：一个是简称，定义时指定；另一个是完全限定名称，其中包含所在包的名称。例如，String 类是 <code>java.lang</code> 包的一部分，因此它的完全限定名称是 <code>java.lang.String</code>。</p>
<p>本节说明如何把自己的类和接口放到包里，以及如何选择包名，避免和其他人的包名有冲突。然后说明如何有选择性地把类型名称或静态成员导入命名空间，避免每次使用类或接口都要输入包名。</p>
<h3 id="声明包"><a href="#声明包" class="headerlink" title="声明包"></a>声明包</h3><p>若想指定类属于哪个包，要使用 package 声明。如果 Java 文件中有 package 关键字，必须是 Java 代码的第一个标记（即除了注释和空格之外的第一个标记）。package 关键字后面是包的名称和一个分号。例如，有个 Java 文件以下述指令开头：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> org.apache.commons.net;</span><br></pre></td></tr></table></figure>

<p>那么，这个文件中定义的所有类都是 <code>org.apache.commons.net</code> 包的一部分。</p>
<p>如果 Java 文件中没有 package 指令，那么这个文件中定义的所有类都是一个默认的无名包的一部分。此时，类的限定名称和不限定名称相同。</p>
<blockquote>
<p>包的名称有可能冲突，所以不要使用默认包。项目在增长的过程中越来越复杂，冲突几乎是不可避免的，所以最好从一开始就创建包。</p>
</blockquote>
<h3 id="全局唯一的包名"><a href="#全局唯一的包名" class="headerlink" title="全局唯一的包名"></a>全局唯一的包名</h3><p>包的重要功能之一是划分 Java 命名空间，避免类名有冲突。例如，只能从包名上区分<code>java.util.List</code> 和 <code>java.awt.List</code> 两个类。不过，因此包名本身就要独一无二。作为 Java的开发方，甲骨文控制着所有以 java、javax 和 sun 开头的包名。</p>
<p>常用的命名方式之一是使用自己的域名，倒序排列各部分，作为包名的前缀。例如，Apache 项目开发了一个网络库，是 Apache Commons 项目的一部分。Commons 项目的网址是 <a href="http://commons.apache.org/，因此这个网络库的包名是" target="_blank" rel="noopener">http://commons.apache.org/，因此这个网络库的包名是</a> <code>org.apache.commons.net</code>。</p>
<p>注意，API 开发者以前也使用这种包命名规则。如果其他程序员要把你开发的类和其他未知类放在一起使用，你的包名就要具有全局唯一性。如果你开发了一个 Java 程序，但是不会发布任何类供他人使用，那么你就知道部署这个应用需要使用的所有类，因此无需担心无法预料的命名冲突。此时，可以选择一种自己用着方便的命名方式，而不用考虑全局唯一性。常见的做法之一是，使用程序的名称作为主包的名称（主包里可能还有子包）。</p>
<h3 id="导入类型"><a href="#导入类型" class="headerlink" title="导入类型"></a>导入类型</h3><p>默认情况下，在 Java 代码中引用类或接口时，必须使用类型的完全限定名称，即包含包名。如果编写的代码需要使用 <code>java.io</code> 包中的 File 类处理文件，必须把这个类写成 <code>java.io.File</code>。不过这个规则有三个例外：</p>
<ul>
<li><code>java.lang</code> 包中的类型很重要也很常用，因此始终可以使用简称引用；</li>
<li>p.T 类型中的代码可以使用简称引用 p 包中定义的其他类型；</li>
<li>已经使用 <code>import</code> 声明导入命名空间里的类型，可以使用简称引用。</li>
</ul>
<p>前两个例外叫作“自动导入”。<code>java.lang</code> 包和当前包中的类型已经导入到命名空间里了，因此可以不加包名。输入不在 <code>java.lang</code> 包或当前包中的常用类型的包名，很快就会变得冗长乏味，因此要能显式地把其他包中的类型导入命名空间。这种操作通过 <code>import</code> 声明实现。</p>
<p><code>import</code> 声明必须放在 Java 文件的开头，如果有 <code>package</code> 声明的话，要紧随其后，并且在任何类型定义之前。一个文件中能使用的 <code>import</code> 声明数量不限。<code>import</code> 声明应用于文件中的所有类型定义（但不应用于 <code>import</code> 声明中的类型）。</p>
<p><code>import</code> 声明有两种格式。若想把单个类型导入命名空间，<code>import</code> 关键字后面是类型的名称和一个分号：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.io.File;    <span class="comment">// 现在不用输入java.io.File了，输入File就行</span></span><br></pre></td></tr></table></figure>

<p>这种格式叫“单个类型导入”声明。<code>import</code> 声明的另一种格式是“按需类型导入”。在这种格式中，包名后面是 <code>.*</code> 字符，表示使用这个包里的任何类型时都不用输入包名。因此，如果除了 File 类之外，还要使用<code>java.io</code> 包中的其他几个类，可以导入整个包：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.io.*;  <span class="comment">// java.io包中的所有类都可以使用简称</span></span><br></pre></td></tr></table></figure>

<p>按需导入句法对子包无效。如果导入了 <code>java.util</code> 包，仍然必须使用完全限定名称<code>java.util.zip.ZipInputStream</code> 引用这个类。按需导入类型和一个一个导入包中的所有类型作用不一样。按需导入更像是使用单个类型导入句法把代码中真正用到的各种类型从包中导入命名空间，因此才叫“按需”导入——<br>用到某个类型时才会将其导入。</p>

    </div>

    
    
    
      
  <div class="popular-posts-header">相关文章</div>
  <ul class="popular-posts">
    <li class="popular-posts-item">
      <div class="popular-posts-title"><a href="\2020\08\08\Java\Java-03-类型系统\" rel="bookmark">Java类型系统</a></div>
    </li>
    <li class="popular-posts-item">
      <div class="popular-posts-title"><a href="\2020\03\23\Java\Java书单\" rel="bookmark">计算机书单</a></div>
    </li>
    <li class="popular-posts-item">
      <div class="popular-posts-title"><a href="\2020\03\21\Java\Java处理常见的数据格式\" rel="bookmark">Java常用类</a></div>
    </li>
    <li class="popular-posts-item">
      <div class="popular-posts-title"><a href="\2020\04\06\Java\Java多线程\" rel="bookmark">Java多线程</a></div>
    </li>
    <li class="popular-posts-item">
      <div class="popular-posts-title"><a href="\2020\04\06\Java\Java容器\" rel="bookmark">Java容器</a></div>
    </li>
  </ul>


      <footer class="post-footer">
          
          <div class="post-tags">
              <a href="/tags/Java/" rel="tag"><i class="fa fa-tag"></i> Java</a>
          </div>

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2019/10/18/Python/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/" rel="prev" title="面向对象">
      <i class="fa fa-chevron-left"></i> 面向对象
    </a></div>
      <div class="post-nav-item">
    <a href="/2020/01/03/Linux%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/" rel="next" title="Linux学习笔记">
      Linux学习笔记 <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#一个简单的Java程序"><span class="nav-number">1.</span> <span class="nav-text">一个简单的Java程序</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#Java程序概览"><span class="nav-number">1.1.</span> <span class="nav-text">Java程序概览</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#基本规则与命名规范"><span class="nav-number">1.2.</span> <span class="nav-text">基本规则与命名规范</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#注释"><span class="nav-number">2.</span> <span class="nav-text">注释</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#词法结构"><span class="nav-number">3.</span> <span class="nav-text">词法结构</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#保留字"><span class="nav-number">3.1.</span> <span class="nav-text">保留字</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#标识符"><span class="nav-number">3.2.</span> <span class="nav-text">标识符</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#字面量"><span class="nav-number">3.3.</span> <span class="nav-text">字面量</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#类"><span class="nav-number">3.4.</span> <span class="nav-text">类</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#方法"><span class="nav-number">3.5.</span> <span class="nav-text">方法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#变量"><span class="nav-number">3.6.</span> <span class="nav-text">变量</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#数据类型"><span class="nav-number">4.</span> <span class="nav-text">数据类型</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#基本数据类型"><span class="nav-number">4.1.</span> <span class="nav-text">基本数据类型</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#整数类型"><span class="nav-number">4.2.</span> <span class="nav-text">整数类型</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#浮点数类型"><span class="nav-number">4.3.</span> <span class="nav-text">浮点数类型</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#布尔类型"><span class="nav-number">4.4.</span> <span class="nav-text">布尔类型</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#字符类型"><span class="nav-number">4.5.</span> <span class="nav-text">字符类型</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#基本类型之间的转换"><span class="nav-number">4.6.</span> <span class="nav-text">基本类型之间的转换</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#数据类型其他有关情况"><span class="nav-number">4.7.</span> <span class="nav-text">数据类型其他有关情况</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#常量"><span class="nav-number">4.7.1.</span> <span class="nav-text">常量</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#var关键字"><span class="nav-number">4.7.2.</span> <span class="nav-text">var关键字</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#变量的作用范围"><span class="nav-number">4.7.3.</span> <span class="nav-text">变量的作用范围</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#表达式和运算符"><span class="nav-number">5.</span> <span class="nav-text">表达式和运算符</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#运算符概述"><span class="nav-number">5.1.</span> <span class="nav-text">运算符概述</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#算术运算符"><span class="nav-number">5.2.</span> <span class="nav-text">算术运算符</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#整数运算"><span class="nav-number">5.2.1.</span> <span class="nav-text">整数运算</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#溢出"><span class="nav-number">5.2.2.</span> <span class="nav-text">溢出</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#字符串连接运算符"><span class="nav-number">5.3.</span> <span class="nav-text">字符串连接运算符</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#递增和递减运算符"><span class="nav-number">5.4.</span> <span class="nav-text">递增和递减运算符</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#比较运算符"><span class="nav-number">5.5.</span> <span class="nav-text">比较运算符</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#逻辑运算符"><span class="nav-number">5.6.</span> <span class="nav-text">逻辑运算符</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#条件与（-amp-amp-）"><span class="nav-number">5.6.1.</span> <span class="nav-text">条件与（&amp;&amp;）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#条件或（-）"><span class="nav-number">5.6.2.</span> <span class="nav-text">条件或（||）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#逻辑非（-）"><span class="nav-number">5.6.3.</span> <span class="nav-text">逻辑非（!）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#逻辑与（-amp-）"><span class="nav-number">5.6.4.</span> <span class="nav-text">逻辑与（&amp;）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#逻辑或（-）"><span class="nav-number">5.6.5.</span> <span class="nav-text">逻辑或（|）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#逻辑异或（-）"><span class="nav-number">5.6.6.</span> <span class="nav-text">逻辑异或（^）</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#位运算符和位移运算符"><span class="nav-number">5.7.</span> <span class="nav-text">位运算符和位移运算符</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#按位补码（-）"><span class="nav-number">5.7.1.</span> <span class="nav-text">按位补码（~）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#位与（-amp-）"><span class="nav-number">5.7.2.</span> <span class="nav-text">位与（&amp;）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#位或（-）"><span class="nav-number">5.7.3.</span> <span class="nav-text">位或（|）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#位异或（-）"><span class="nav-number">5.7.4.</span> <span class="nav-text">位异或（^）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#左移（-lt-lt-）"><span class="nav-number">5.7.5.</span> <span class="nav-text">左移（&lt;&lt;）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#带符号右移（-gt-gt-）"><span class="nav-number">5.7.6.</span> <span class="nav-text">带符号右移（&gt;&gt;）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#不带符号右移（-gt-gt-gt-）"><span class="nav-number">5.7.7.</span> <span class="nav-text">不带符号右移（&gt;&gt;&gt;）</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#赋值运算符"><span class="nav-number">5.8.</span> <span class="nav-text">赋值运算符</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#条件运算符"><span class="nav-number">5.9.</span> <span class="nav-text">条件运算符</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#instanceof操作符"><span class="nav-number">5.10.</span> <span class="nav-text">instanceof操作符</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#特殊运算符"><span class="nav-number">5.11.</span> <span class="nav-text">特殊运算符</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#其他运算"><span class="nav-number">5.12.</span> <span class="nav-text">其他运算</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#类型自动提升与强制转型"><span class="nav-number">5.12.1.</span> <span class="nav-text">类型自动提升与强制转型</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#浮点数的运算"><span class="nav-number">5.12.2.</span> <span class="nav-text">浮点数的运算</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#赋值与别名"><span class="nav-number">5.12.3.</span> <span class="nav-text">赋值与别名</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#字符和字符串"><span class="nav-number">5.13.</span> <span class="nav-text">字符和字符串</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#字符的类型"><span class="nav-number">5.13.1.</span> <span class="nav-text">字符的类型</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#字符串类型"><span class="nav-number">5.13.2.</span> <span class="nav-text">字符串类型</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#字符串连接"><span class="nav-number">5.13.3.</span> <span class="nav-text">字符串连接</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#多行字符串"><span class="nav-number">5.13.4.</span> <span class="nav-text">多行字符串</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#不可变特性"><span class="nav-number">5.13.5.</span> <span class="nav-text">不可变特性</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#空值null"><span class="nav-number">5.13.6.</span> <span class="nav-text">空值null</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#类型转换"><span class="nav-number">5.13.7.</span> <span class="nav-text">类型转换</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#语句"><span class="nav-number">6.</span> <span class="nav-text">语句</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#表达式语句"><span class="nav-number">6.1.</span> <span class="nav-text">表达式语句</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#复合语句"><span class="nav-number">6.2.</span> <span class="nav-text">复合语句</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#空语句"><span class="nav-number">6.3.</span> <span class="nav-text">空语句</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#标注语句"><span class="nav-number">6.4.</span> <span class="nav-text">标注语句</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#局部变量声明语句"><span class="nav-number">6.5.</span> <span class="nav-text">局部变量声明语句</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#if-else语句"><span class="nav-number">6.6.</span> <span class="nav-text">if&#x2F;else语句</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#switch多重选择"><span class="nav-number">6.7.</span> <span class="nav-text">switch多重选择</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#switch表达式"><span class="nav-number">6.7.1.</span> <span class="nav-text">switch表达式</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#yield"><span class="nav-number">6.7.2.</span> <span class="nav-text">yield</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#while循环"><span class="nav-number">6.8.</span> <span class="nav-text">while循环</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#do-while循环"><span class="nav-number">6.8.1.</span> <span class="nav-text">do while循环</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#for循环"><span class="nav-number">6.9.</span> <span class="nav-text">for循环</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#灵活使用for循环"><span class="nav-number">6.9.1.</span> <span class="nav-text">灵活使用for循环</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#for-each循环"><span class="nav-number">6.9.2.</span> <span class="nav-text">for each循环</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#break和continue"><span class="nav-number">6.10.</span> <span class="nav-text">break和continue</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#break"><span class="nav-number">6.10.1.</span> <span class="nav-text">break</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#continue"><span class="nav-number">6.10.2.</span> <span class="nav-text">continue</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#throw语句"><span class="nav-number">6.11.</span> <span class="nav-text">throw语句</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#assert语句"><span class="nav-number">6.12.</span> <span class="nav-text">assert语句</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#synchronized语句"><span class="nav-number">6.13.</span> <span class="nav-text">synchronized语句</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#try-catch-finally语句"><span class="nav-number">6.14.</span> <span class="nav-text">try&#x2F;catch&#x2F;finally语句</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#try子句"><span class="nav-number">6.14.1.</span> <span class="nav-text">try子句</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#catch子句"><span class="nav-number">6.14.2.</span> <span class="nav-text">catch子句</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#finally子句"><span class="nav-number">6.14.3.</span> <span class="nav-text">finally子句</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#处理资源的try语句"><span class="nav-number">6.15.</span> <span class="nav-text">处理资源的try语句</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#方法-1"><span class="nav-number">7.</span> <span class="nav-text">方法</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#定义方法"><span class="nav-number">7.1.</span> <span class="nav-text">定义方法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#方法修饰符"><span class="nav-number">7.2.</span> <span class="nav-text">方法修饰符</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#abstract"><span class="nav-number">7.2.1.</span> <span class="nav-text">abstract</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#final"><span class="nav-number">7.2.2.</span> <span class="nav-text">final</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#native"><span class="nav-number">7.2.3.</span> <span class="nav-text">native</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#public、protected、private"><span class="nav-number">7.2.4.</span> <span class="nav-text">public、protected、private</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#static"><span class="nav-number">7.2.5.</span> <span class="nav-text">static</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#strictfp"><span class="nav-number">7.2.6.</span> <span class="nav-text">strictfp</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#synchronized"><span class="nav-number">7.2.7.</span> <span class="nav-text">synchronized</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#已检异常和未检异常"><span class="nav-number">7.3.</span> <span class="nav-text">已检异常和未检异常</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#变长参数列表"><span class="nav-number">7.4.</span> <span class="nav-text">变长参数列表</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#类和对象"><span class="nav-number">8.</span> <span class="nav-text">类和对象</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#定义类"><span class="nav-number">8.1.</span> <span class="nav-text">定义类</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#创建对象"><span class="nav-number">8.2.</span> <span class="nav-text">创建对象</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#使用对象"><span class="nav-number">8.3.</span> <span class="nav-text">使用对象</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#对象字面量"><span class="nav-number">8.4.</span> <span class="nav-text">对象字面量</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#字符串字面量"><span class="nav-number">8.4.1.</span> <span class="nav-text">字符串字面量</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#类型字面量"><span class="nav-number">8.4.2.</span> <span class="nav-text">类型字面量</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#null引用"><span class="nav-number">8.4.3.</span> <span class="nav-text">null引用</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#lambda表达式"><span class="nav-number">8.5.</span> <span class="nav-text">lambda表达式</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#数组"><span class="nav-number">9.</span> <span class="nav-text">数组</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#数组的类型"><span class="nav-number">9.1.</span> <span class="nav-text">数组的类型</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#创建和初始化数组"><span class="nav-number">9.2.</span> <span class="nav-text">创建和初始化数组</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#使用数组"><span class="nav-number">9.3.</span> <span class="nav-text">使用数组</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#访问数组中的元素"><span class="nav-number">9.3.1.</span> <span class="nav-text">访问数组中的元素</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#数组的边界"><span class="nav-number">9.3.2.</span> <span class="nav-text">数组的边界</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#迭代数组"><span class="nav-number">9.3.3.</span> <span class="nav-text">迭代数组</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#复制数组"><span class="nav-number">9.3.4.</span> <span class="nav-text">复制数组</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#数组的实用方法"><span class="nav-number">9.3.5.</span> <span class="nav-text">数组的实用方法</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#多维数组"><span class="nav-number">9.4.</span> <span class="nav-text">多维数组</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#数组存储的弊端"><span class="nav-number">9.5.</span> <span class="nav-text">数组存储的弊端</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#引用类型"><span class="nav-number">10.</span> <span class="nav-text">引用类型</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#引用类型与基本类型比较"><span class="nav-number">10.1.</span> <span class="nav-text">引用类型与基本类型比较</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#处理对象和引用副本"><span class="nav-number">10.2.</span> <span class="nav-text">处理对象和引用副本</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#比较对象"><span class="nav-number">10.3.</span> <span class="nav-text">比较对象</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#装包和拆包转换"><span class="nav-number">10.4.</span> <span class="nav-text">装包和拆包转换</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#包和Java命名空间"><span class="nav-number">11.</span> <span class="nav-text">包和Java命名空间</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#声明包"><span class="nav-number">11.1.</span> <span class="nav-text">声明包</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#全局唯一的包名"><span class="nav-number">11.2.</span> <span class="nav-text">全局唯一的包名</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#导入类型"><span class="nav-number">11.3.</span> <span class="nav-text">导入类型</span></a></li></ol></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="Lanqilu"
      src="http://img.whl123456.top/image/avatar.jpg">
  <p class="site-author-name" itemprop="name">Lanqilu</p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">85</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">18</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">39</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/lanqilu" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;lanqilu" rel="noopener" target="_blank"><i class="fa fa-fw fa-github"></i></a>
      </span>
      <span class="links-of-author-item">
        <a href="http://mail.qq.com/cgi-bin/qm_share?t=qm_mailme&email=zqKvoL_noruOqKG2o6_nouCtoaM" title="E-Mail → http:&#x2F;&#x2F;mail.qq.com&#x2F;cgi-bin&#x2F;qm_share?t&#x3D;qm_mailme&amp;email&#x3D;zqKvoL_noruOqKG2o6_nouCtoaM" rel="noopener" target="_blank"><i class="fa fa-fw fa-envelope"></i></a>
      </span>
  </div>



      </div>
        <div class="back-to-top motion-element">
          <i class="fa fa-arrow-up"></i>
          <span>0%</span>
        </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 2019 – 
  <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Lanqilu</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Gemini</a> 强力驱动
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/pjax/pjax.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js"></script>
  <script src="//cdn.jsdelivr.net/gh/fancyapps/fancybox@3/dist/jquery.fancybox.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/pangu@4/dist/browser/pangu.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>

  <script>
var pjax = new Pjax({
  selectors: [
    'head title',
    '#page-configurations',
    '.content-wrap',
    '.post-toc-wrap',
    '.languages',
    '#pjax'
  ],
  switches: {
    '.post-toc-wrap': Pjax.switches.innerHTML
  },
  analytics: false,
  cacheBust: false,
  scrollTo : !CONFIG.bookmark.enable
});

window.addEventListener('pjax:success', () => {
  document.querySelectorAll('script[data-pjax], script#page-configurations, #pjax script').forEach(element => {
    var code = element.text || element.textContent || element.innerHTML || '';
    var parent = element.parentNode;
    parent.removeChild(element);
    var script = document.createElement('script');
    if (element.id) {
      script.id = element.id;
    }
    if (element.className) {
      script.className = element.className;
    }
    if (element.type) {
      script.type = element.type;
    }
    if (element.src) {
      script.src = element.src;
      // Force synchronous loading of peripheral JS.
      script.async = false;
    }
    if (element.dataset.pjax !== undefined) {
      script.dataset.pjax = '';
    }
    if (code !== '') {
      script.appendChild(document.createTextNode(code));
    }
    parent.appendChild(script);
  });
  NexT.boot.refresh();
  // Define Motion Sequence & Bootstrap Motion.
  if (CONFIG.motion.enable) {
    NexT.motion.integrator
      .init()
      .add(NexT.motion.middleWares.subMenu)
      .add(NexT.motion.middleWares.postList)
      .bootstrap();
  }
  NexT.utils.updateSidebarPosition();
});
</script>




  




  
<script src="/js/local-search.js"></script>













    <div id="pjax">
  

  

  

    </div>
</body>
</html>
